home *** CD-ROM | disk | FTP | other *** search
/ Gamers Delight 2 / Gamers Delight 2.iso / Aminet / game / role / Ang261Lib.lha / src / spells.c < prev    next >
C/C++ Source or Header  |  1994-10-22  |  138KB  |  5,007 lines

  1. /*
  2.  * spells.c: code for player and creature spells, breaths, wands, scrolls,
  3.  * etc. 
  4.  *
  5.  * Copyright (c) 1989 James E. Wilson, Robert A. Koeneke 
  6.  *
  7.  * This software may be copied and distributed for educational, research, and
  8.  * not for profit purposes provided that this copyright and statement are
  9.  * included in all such copies. 
  10.  */
  11.  
  12. #include "constant.h"
  13. #include "config.h"
  14. #include "types.h"
  15. #include "monster.h"
  16. #include "externs.h"
  17.  
  18. #ifdef USG
  19. #ifndef ATARIST_MWC
  20. #include <string.h>
  21. #endif
  22. #else
  23. #ifndef VMS
  24. #include <strings.h>
  25. #endif
  26. #endif
  27.  
  28. /* Lets do all prototypes correctly.... -CWS */
  29. #ifndef NO_LINT_ARGS
  30. #ifdef __STDC__
  31. static char bolt_char(int, int, int, int);
  32. static void ball_destroy(int, int (**) ());
  33. static void pause_if_screen_full(int *, int);
  34. static void spell_hit_monster(monster_type *, int, int *, int, int *, int *, int8u);
  35. static void replace_spot(int, int, int);
  36. #else
  37. static char bolt_char();
  38. static void ball_destroy();
  39. static void pause_if_screen_full();
  40. static void spell_hit_monster();
  41. static void replace_spot();
  42. #endif
  43. #endif
  44.  
  45. /* Following are spell procedure/functions            -RAK-     */
  46. /* These routines are commonly used in the scroll, potion, wands, and     */
  47. /* staves routines, and are occasionally called from other areas.      */
  48. /* Now included are creature spells also.               -RAK    */
  49.  
  50. /* this assumes only 1 move apart -CFT */
  51. static char
  52. bolt_char(y, x, ny, nx)
  53. int y, x, ny, nx;
  54. {
  55.     if (ny == y) return '-';
  56.     if (nx == x) return '|';
  57.     if ((ny-y) == (nx-x)) return '\\';
  58.     return '/';
  59. }
  60.  
  61. /* return the appropriate item destroy test to the typ.  All that's left of
  62.  * get_flags().  -CFT 
  63.  */
  64.  
  65. /*
  66.  * add new destroys?  maybe GF_FORCE destroy potions, GF_PLASMA as lightning,
  67.  * GF_SHARDS and GF_ICE maybe break things (potions?), and GF_METEOR breaks
  68.  * potions and burns scrolls?  not yet, but it's an idea... -CFT 
  69.  */
  70. static void 
  71. ball_destroy(typ, destroy)
  72. int typ;
  73. int (**destroy) ();
  74.  
  75. {
  76.     switch (typ) {
  77.       case GF_FIRE:
  78.     *destroy = set_fire_destroy;
  79.     break;
  80.       case GF_ACID:
  81.     *destroy = set_acid_destroy;
  82.     break;
  83.       case GF_FROST:
  84.       case GF_SHARDS:
  85.       case GF_ICE:
  86.       case GF_FORCE:
  87.       case GF_SOUND:
  88.     *destroy = set_frost_destroy;    /* just potions and flasks -DGK */
  89.     break;
  90.       case GF_LIGHTNING:
  91.     *destroy = set_lightning_destroy;
  92.     break;
  93.       case GF_PLASMA:           /* DGK */
  94.     *destroy = set_plasma_destroy;    /* fire+lightning -DGK */
  95.     break;
  96.       case GF_METEOR:           /* DGK */
  97.     *destroy = set_meteor_destroy;    /* fire+shards -DGK */
  98.     break;
  99.       case GF_MANA:           /* DGK */
  100.     *destroy = set_mana_destroy;    /* everything -DGK */
  101.     break;
  102.       case GF_HOLY_ORB:       /* DGK */
  103.     *destroy = set_holy_destroy;    /* cursed stuff -DGK */
  104.     break;
  105.       case GF_MAGIC_MISSILE:
  106.       case GF_POISON_GAS:
  107.       case GF_ARROW:
  108.       case GF_NETHER:
  109.       case GF_WATER:
  110.       case GF_CHAOS:
  111.       case GF_CONFUSION:
  112.       case GF_DISENCHANT:
  113.       case GF_NEXUS:
  114.       case GF_INERTIA:
  115.       case GF_LIGHT:
  116.       case GF_DARK:
  117.       case GF_TIME:
  118.       case GF_GRAVITY:
  119.     *destroy = set_null;
  120.     break;
  121.       default:
  122.     msg_print("Unknown typ in ball_destroy().  This may mean trouble.");
  123.     *destroy = set_null;
  124.     break;
  125.     }
  126. }
  127.  
  128. void 
  129. monster_name(m_name, m_ptr, r_ptr)
  130. char               *m_name;
  131. monster_type       *m_ptr;
  132. creature_type      *r_ptr;
  133. {
  134.     if (!m_ptr->ml)
  135.     (void)strcpy(m_name, "It");
  136.     else {
  137.     if (r_ptr->cdefense & UNIQUE)
  138.         (void)sprintf(m_name, "%s", r_ptr->name);
  139.     else
  140.         (void)sprintf(m_name, "The %s", r_ptr->name);
  141.     }
  142. }
  143.  
  144. void 
  145. lower_monster_name(m_name, m_ptr, r_ptr)
  146. char               *m_name;
  147. monster_type       *m_ptr;
  148. creature_type      *r_ptr;
  149. {
  150.     if (!m_ptr->ml)
  151.     (void)strcpy(m_name, "it");
  152.     else {
  153.     if (r_ptr->cdefense & UNIQUE)
  154.         (void)sprintf(m_name, "%s", r_ptr->name);
  155.     else
  156.         (void)sprintf(m_name, "the %s", r_ptr->name);
  157.     }
  158. }
  159.  
  160. /* teleport you a level (or three:-) */
  161. void 
  162. tele_level()
  163. {
  164.     if (dun_level == Q_PLANE)
  165.     dun_level = 0;
  166.     else if (is_quest(dun_level))
  167.     dun_level -= 1;
  168.     else
  169.     dun_level += (-3) + 2 * randint(2);
  170.     if (dun_level < 0)
  171.     dun_level = 0;
  172.     new_level_flag = TRUE;
  173. }
  174.  
  175. /* Sleep creatures adjacent to player            -RAK-     */
  176. int 
  177. sleep_monsters1(y, x)
  178. int y, x;
  179. {
  180.     register int            i, j;
  181.     register cave_type     *c_ptr;
  182.     register monster_type  *m_ptr;
  183.     register creature_type *r_ptr;
  184.     int                     sleep;
  185.     vtype                   out_val, m_name;
  186.  
  187.     sleep = FALSE;
  188.     for (i = y - 1; i <= y + 1; i++)
  189.     for (j = x - 1; j <= x + 1; j++) {
  190.         c_ptr = &cave[i][j];
  191.         if (c_ptr->cptr > 1) {
  192.         m_ptr = &m_list[c_ptr->cptr];
  193.         r_ptr = &c_list[m_ptr->mptr];
  194.  
  195.         monster_name(m_name, m_ptr, r_ptr);
  196.         if ((r_ptr->level >
  197.              randint((py.misc.lev - 10) < 1 ? 1 : (py.misc.lev - 10)) + 10) ||
  198.             (CHARM_SLEEP & r_ptr->cdefense) || (r_ptr->cdefense & UNIQUE)) {
  199.             if (m_ptr->ml && (r_ptr->cdefense & CHARM_SLEEP))
  200.             c_recall[m_ptr->mptr].r_cdefense |= CHARM_SLEEP;
  201.             (void)sprintf(out_val, "%s is unaffected.", m_name);
  202.             msg_print(out_val);
  203.         } else {
  204.             sleep = TRUE;
  205.             m_ptr->csleep = 500;
  206.             (void)sprintf(out_val, "%s falls asleep.", m_name);
  207.             msg_print(out_val);
  208.         }
  209.         }
  210.     }
  211.     return (sleep);
  212. }
  213.  
  214. int 
  215. lose_all_info()
  216. {
  217.     int                 i;
  218.  
  219.     for (i = 0; i <= INVEN_AUX; i++) {
  220.     if (inventory[i].tval != TV_NOTHING)
  221.         inventory[i].ident &= ~(ID_KNOWN2);
  222.     }
  223.     wizard_light(-1);
  224.     return (0);
  225. }
  226.  
  227. void 
  228. identify_pack()
  229. {
  230.     int                 i;
  231.     inven_type         *i_ptr;
  232.  
  233.     for (i = 0; i <= INVEN_AUX; i++) {
  234.     if (inventory[i].tval != TV_NOTHING)
  235.         identify(&i);
  236.     i_ptr = &inventory[i];
  237.     known2(i_ptr);
  238.     }
  239. }
  240.  
  241. /* Detect any treasure on the current panel        -RAK-     */
  242. int 
  243. detect_treasure()
  244. {
  245.     register int        i, j, detect;
  246.     register cave_type *c_ptr;
  247.  
  248.     detect = FALSE;
  249.     for (i = panel_row_min; i <= panel_row_max; i++)
  250.     for (j = panel_col_min; j <= panel_col_max; j++) {
  251.         c_ptr = &cave[i][j];
  252.         if ((c_ptr->tptr != 0) && (t_list[c_ptr->tptr].tval == TV_GOLD) &&
  253.         !test_light(i, j)) {
  254.         c_ptr->fm = TRUE;
  255.         lite_spot(i, j);
  256.         detect = TRUE;
  257.         }
  258.     }
  259.     return (detect);
  260. }
  261.  
  262. /* This will light up all spaces with "magic" items, including potions,
  263.  * scrolls, rods, wands, staves, amulets, rings, and "enchanted" items. This
  264.  * excludes all foods and spell books. -- JND  
  265.  */
  266.  
  267. int 
  268. detect_magic()
  269. {
  270.     register int         i, j, detect;
  271.     register cave_type  *c_ptr;
  272.     register inven_type *t_ptr;
  273.     int                  Tval;
  274.  
  275.     detect = FALSE;
  276.     for (i = panel_row_min; i <= panel_row_max; i++)
  277.     for (j = panel_col_min; j <= panel_col_max; j++) {
  278.         c_ptr = &cave[i][j];
  279.         if ((c_ptr->tptr != 0) && (t_list[c_ptr->tptr].tval < TV_MAX_OBJECT)
  280.         && !test_light(i, j)) {
  281.         t_ptr = &t_list[c_ptr->tptr];
  282.         Tval = t_ptr->tval;
  283.             /* Is it a weapon or armor or light? */
  284.         if (((Tval > 9) && (Tval < 39)) &&
  285.             (((t_ptr->tohit > 0) || (t_ptr->todam) || (t_ptr->toac)
  286.         /* If so, check for plusses on weapons and armor ... */
  287.               || (t_ptr->flags2 & TR_ARTIFACT))
  288.         /* ... and check whether it is an artifact! ;)  */
  289.              || ((Tval > 39) && (Tval < 77)))){    /* Is it otherwise magical? */
  290.             c_ptr->fm = TRUE;
  291.             lite_spot(i, j);
  292.             detect = TRUE;
  293.         }
  294.         }
  295.     }
  296.     return (detect);
  297. }
  298.  
  299.  
  300.  
  301. int 
  302. detect_enchantment()
  303. {
  304.     register int i, j, detect, tv;
  305.     register cave_type *c_ptr;
  306.     
  307.     detect = FALSE;
  308.     for (i = panel_row_min; i <= panel_row_max; i++)
  309.     for (j = panel_col_min; j <= panel_col_max; j++) {
  310.         c_ptr = &cave[i][j];
  311.         tv = t_list[c_ptr->tptr].tval;
  312.         if ((c_ptr->tptr != 0) && !test_light(i, j) &&
  313.         ( ((tv > TV_MAX_ENCHANT) && (tv < TV_FLASK)) || /* misc items */
  314.          (tv == TV_MAGIC_BOOK) || (tv == TV_PRAYER_BOOK) || /* books */
  315.          ((tv >= TV_MIN_WEAR) && (tv <= TV_MAX_ENCHANT) && /* armor/weap */
  316.           ((t_list[c_ptr->tptr].flags2 & TR_ARTIFACT) || /* if Art., or */
  317.            (t_list[c_ptr->tptr].tohit>0) || /* has pluses, then show */
  318.            (t_list[c_ptr->tptr].todam>0) ||
  319.            (t_list[c_ptr->tptr].toac>0))) )){
  320.         c_ptr->fm = TRUE;
  321.         lite_spot(i, j);
  322.         detect = TRUE;
  323.         }
  324.     }
  325.     return(detect);
  326. }
  327.  
  328. int 
  329. detection()
  330. {
  331.     register int           i, detect;
  332.     register monster_type *m_ptr;
  333.  
  334.     detect_treasure();
  335.     detect_object();
  336.     detect_trap();
  337.     detect_sdoor();
  338.  
  339.     detect = FALSE;
  340.     for (i = mfptr - 1; i >= MIN_MONIX; i--) {
  341.     m_ptr = &m_list[i];
  342.     if (panel_contains((int)m_ptr->fy, (int)m_ptr->fx)) {
  343.         m_ptr->ml = TRUE;
  344.     /* works correctly even if hallucinating */
  345.         print((char)c_list[m_ptr->mptr].cchar, (int)m_ptr->fy,
  346.           (int)m_ptr->fx);
  347.         detect = TRUE;
  348.     }
  349.     }
  350.     if (detect) {
  351.     msg_print("You sense the presence of monsters!");
  352.     msg_print(NULL);
  353.     /* must unlight every monster just lighted */
  354.     creatures(FALSE);
  355.     }
  356.     return (detect);
  357. }
  358.  
  359. /* Detect all objects on the current panel        -RAK-     */
  360. int 
  361. detect_object()
  362. {
  363.     register int        i, j, detect;
  364.     register cave_type *c_ptr;
  365.  
  366.     detect = FALSE;
  367.     for (i = panel_row_min; i <= panel_row_max; i++)
  368.     for (j = panel_col_min; j <= panel_col_max; j++) {
  369.         c_ptr = &cave[i][j];
  370.         if ((c_ptr->tptr != 0) && (t_list[c_ptr->tptr].tval < TV_MAX_OBJECT)
  371.         && !test_light(i, j)) {
  372.         c_ptr->fm = TRUE;
  373.         lite_spot(i, j);
  374.         detect = TRUE;
  375.         }
  376.     }
  377.     return (detect);
  378. }
  379.  
  380.  
  381. /* Locates and displays traps on current panel        -RAK-     */
  382. int 
  383. detect_trap()
  384. {
  385.     register int         i, j;
  386.     int                  detect;
  387.     register cave_type  *c_ptr;
  388.     register inven_type *t_ptr;
  389.  
  390.     detect = FALSE;
  391.     for (i = panel_row_min; i <= panel_row_max; i++)
  392.     for (j = panel_col_min; j <= panel_col_max; j++) {
  393.         c_ptr = &cave[i][j];
  394.         if (c_ptr->tptr != 0)
  395.         if (t_list[c_ptr->tptr].tval == TV_INVIS_TRAP) {
  396.             c_ptr->fm = TRUE;
  397.             change_trap(i, j);
  398.             detect = TRUE;
  399.         } else if (t_list[c_ptr->tptr].tval == TV_CHEST) {
  400.             t_ptr = &t_list[c_ptr->tptr];
  401.             known2(t_ptr);
  402.         }
  403.     }
  404.     return (detect);
  405. }
  406.  
  407. void 
  408. stair_creation()
  409. {
  410.     register cave_type *c_ptr;
  411.     register int        cur_pos;
  412.  
  413.     c_ptr = &cave[char_row][char_col];
  414.  
  415.     if ((c_ptr->tptr == 0) ||
  416.         ((t_list[c_ptr->tptr].tval != TV_UP_STAIR)  /* if not stairs or a store */
  417.          && (t_list[c_ptr->tptr].tval != TV_DOWN_STAIR)
  418.          && (t_list[c_ptr->tptr].tval != TV_STORE_DOOR)
  419.          && ((t_list[c_ptr->tptr].tval < TV_MIN_WEAR) ||
  420.              (t_list[c_ptr->tptr].tval > TV_MAX_WEAR) ||
  421.              !(t_list[c_ptr->tptr].flags2 & TR_ARTIFACT)))) {
  422. /* if no artifact here -CFT */
  423.     if (c_ptr->tptr != 0)
  424.         (void)delete_object(char_row, char_col);
  425.     cur_pos = popt();
  426.     c_ptr->tptr = cur_pos;
  427.     if ((randint(2) == 1 || is_quest(dun_level)) && (dun_level > 0))
  428.         invcopy(&t_list[cur_pos], OBJ_UP_STAIR);
  429.     else
  430.         invcopy(&t_list[cur_pos], OBJ_DOWN_STAIR);
  431.     } else
  432.     msg_print("The object resists the spell.");
  433. }
  434.  
  435. /* Surround the player with doors.            -RAK-     */
  436. int 
  437. door_creation()
  438. {
  439.     register int        i, j, door;
  440.     int                 k;
  441.     register cave_type *c_ptr;
  442.  
  443.     door = FALSE;
  444.     for (i = char_row - 1; i <= char_row + 1; i++)
  445.     for (j = char_col - 1; j <= char_col + 1; j++)
  446.         if ((i != char_row) || (j != char_col)) {
  447.         c_ptr = &cave[i][j];
  448.         if (c_ptr->fval <= MAX_CAVE_FLOOR) {
  449.             if ((c_ptr->tptr == 0) ||
  450.             ((t_list[c_ptr->tptr].tval != TV_UP_STAIR) 
  451.                 /* if not stairs or a store */
  452.              &&(t_list[c_ptr->tptr].tval != TV_DOWN_STAIR)
  453.              && (t_list[c_ptr->tptr].tval != TV_STORE_DOOR)) ||
  454.             (t_list[c_ptr->tptr].tval < TV_MIN_WEAR) ||
  455.             (t_list[c_ptr->tptr].tval > TV_MAX_WEAR) ||
  456.             !(t_list[c_ptr->tptr].flags2 & TR_ARTIFACT)) {
  457.                 /* if no artifact here -CFT */
  458.             door = TRUE;
  459.             if (c_ptr->tptr != 0)
  460.                 (void)delete_object(i, j);
  461.             k = popt();
  462.             c_ptr->fval = BLOCKED_FLOOR;
  463.             c_ptr->tptr = k;
  464.             invcopy(&t_list[k], OBJ_CLOSED_DOOR);
  465.             lite_spot(i, j);
  466.             } else
  467.             msg_print("The object resists the spell.");
  468.         }
  469.         }
  470.     return (door);
  471. }
  472.  
  473. /* Locates and displays all secret doors on current panel -RAK-     */
  474. int 
  475. detect_sdoor()
  476. {
  477.     register int        i, j, detect;
  478.     register cave_type *c_ptr;
  479.  
  480.     detect = FALSE;
  481.     for (i = panel_row_min; i <= panel_row_max; i++)
  482.     for (j = panel_col_min; j <= panel_col_max; j++) {
  483.         c_ptr = &cave[i][j];
  484.         if (c_ptr->tptr != 0)
  485.         /* Secret doors  */
  486.         if (t_list[c_ptr->tptr].tval == TV_SECRET_DOOR) {
  487.             c_ptr->fm = TRUE;
  488.             change_trap(i, j);
  489.             detect = TRUE;
  490.         }
  491.     /* Staircases     */
  492.         else if (((t_list[c_ptr->tptr].tval == TV_UP_STAIR) ||
  493.               (t_list[c_ptr->tptr].tval == TV_DOWN_STAIR)) &&
  494.              !c_ptr->fm) {
  495.             c_ptr->fm = TRUE;
  496.             lite_spot(i, j);
  497.             detect = TRUE;
  498.         }
  499.     }
  500.     return (detect);
  501. }
  502.  
  503.  
  504. /* Locates and displays all invisible creatures on current panel -RAK- */
  505. int 
  506. detect_invisible()
  507. {
  508.     register int           i, flag;
  509.     register monster_type *m_ptr;
  510.  
  511.     flag = FALSE;
  512.     for (i = mfptr - 1; i >= MIN_MONIX; i--) {
  513.     m_ptr = &m_list[i];
  514.     if (panel_contains((int)m_ptr->fy, (int)m_ptr->fx) &&
  515.         (CM_INVISIBLE & c_list[m_ptr->mptr].cmove)) {
  516.         m_ptr->ml = TRUE;
  517.     /* works correctly even if hallucinating */
  518.         print((char)c_list[m_ptr->mptr].cchar, (int)m_ptr->fy,
  519.           (int)m_ptr->fx);
  520.         flag = TRUE;
  521.     }
  522.     }
  523.     if (flag) {
  524.     msg_print("You sense the presence of invisible creatures!");
  525.     msg_print(NULL);
  526.     /* must unlight every monster just lighted */
  527.     creatures(FALSE);
  528.     }
  529.     return (flag);
  530. }
  531.  
  532.  
  533. /* Split out of light_line.       -DGK */
  534. void 
  535. mon_light_dam(y, x, dam)
  536. int y, x, dam;
  537. {
  538.     register cave_type     *c_ptr;
  539.     register monster_type  *m_ptr;
  540.     register creature_type *r_ptr;
  541.     vtype                   out_val, m_name;
  542.     int                     i;
  543.  
  544.     c_ptr = &cave[y][x];
  545.     if (c_ptr->cptr > 1) {
  546.     m_ptr = &m_list[c_ptr->cptr];
  547.     r_ptr = &c_list[m_ptr->mptr];
  548.     monster_name(m_name, m_ptr, r_ptr);
  549.     m_ptr->csleep = 0;
  550.     if (HURT_LIGHT & r_ptr->cdefense) {
  551.         if (m_ptr->ml)
  552.         c_recall[m_ptr->mptr].r_cdefense |= HURT_LIGHT;
  553.         i = mon_take_hit((int)c_ptr->cptr, dam, FALSE);
  554.         if (i >= 0) {
  555.         (void)sprintf(out_val, "%s shrivels away in the light!", m_name);
  556.         msg_print(out_val);
  557.         prt_experience();
  558.         } else {
  559.         (void)sprintf(out_val, "%s cringes from the light!", m_name);
  560.         msg_print(out_val);
  561.         }
  562.     }
  563.     }
  564. }
  565.  
  566.  
  567. int 
  568. light_area(y, x, dam, rad)       /* Expanded -DGK */
  569. register int y, x, dam, rad;
  570. {
  571.     register int i, j;
  572.     int          min_i, max_i, min_j, max_j;
  573.  
  574.     if (rad < 1) rad = 1;    /* sanity check -CWS */
  575.     if (py.flags.blind < 1)
  576.     msg_print("You are surrounded by a white light.");
  577.  
  578.     if ((cave[y][x].fval == LIGHT_FLOOR) && (panel_contains(y, x)))
  579.     light_room(y, x);
  580.  
  581.     if (cave[y][x].lr && (dun_level > 0) && !(cave[y][x].pl))
  582.         light_room(y, x); /* dbd - fix lighting radius */
  583.  
  584.     /* replace a check for in_bounds2 every loop with 4 quick computations -CWS */
  585.     min_i = MY_MAX(0, (y - rad));
  586.     max_i = MY_MIN(cur_height - 1, (y + rad));
  587.     min_j = MY_MAX(0, (x - rad));
  588.     max_j = MY_MIN(cur_width - 1, (x + rad));
  589.  
  590.     for (i = min_i; i <= max_i; i++)
  591.     for (j = min_j; j <= max_j; j++)
  592.         if (los(y, x, i, j) && (distance(y, x, i, j) <= rad)) {
  593.         if (cave[i][j].lr && (dun_level > 0))
  594.             light_room(i, j);
  595.         cave[i][j].pl = TRUE;
  596.         lite_spot(i, j);
  597.         if (dam)
  598.             mon_light_dam(i, j, dam / (rad == 0 ? 1 : rad));
  599.         }
  600.     return (TRUE);
  601. }
  602.  
  603.  
  604. /* Darken an area, opposite of light area        -RAK-     */
  605. int 
  606. unlight_area(y, x)
  607. int y, x;
  608. {
  609.     register int        i, j, unlight;
  610.     register cave_type *c_ptr;
  611.     int                 min_i, max_i, min_j, max_j;
  612.  
  613.     unlight = FALSE;
  614.     if (cave[y][x].lr && (dun_level > 0)) {
  615.     darken_room(y, x);
  616.     unlight = TRUE;
  617. /* this isn't really good, as it returns true, even if rm was already dark, but
  618.  * at least scrolls of darkness will be IDed when used -CFT
  619.  */
  620.     } else {
  621.     min_i = MY_MAX(0, (y - 3));
  622.     max_i = MY_MIN(cur_height - 1, (y + 3));
  623.     min_j = MY_MAX(0, (x - 3));
  624.     max_j = MY_MIN(cur_width - 1, (x + 3));
  625.     
  626.     /* replace a check for in_bounds2 every loop with 4 quick computations -CWS */
  627.     
  628.     for (i = min_i; i <= max_i; i++)
  629.         for (j = min_j; j <= max_j; j++) {
  630.         c_ptr = &cave[i][j];
  631.         if ((c_ptr->fval == CORR_FLOOR) && (c_ptr->pl || c_ptr->lr)) {
  632.             /* pl could have been set by star-lite wand, etc */
  633.             c_ptr->pl = FALSE;
  634.             c_ptr->tl = FALSE;
  635.             unlight = TRUE;
  636.         }
  637.         }
  638.     }
  639.     if (unlight && py.flags.blind <= 0)
  640.     msg_print("Darkness surrounds you.");
  641.  
  642.     return (unlight);
  643. }
  644.  
  645.  
  646. /* Map the current area plus some            -RAK-     */
  647. void 
  648. map_area()
  649. {
  650.     register cave_type *c_ptr;
  651.     register int        i7, i8, n, m;
  652.     int                 i, j, k, l;
  653.  
  654.     i = panel_row_min - randint(10);
  655.     j = panel_row_max + randint(10);
  656.     k = panel_col_min - randint(20);
  657.     l = panel_col_max + randint(20);
  658.     for (m = i; m <= j; m++)
  659.     for (n = k; n <= l; n++)
  660.         if (in_bounds(m, n) && (cave[m][n].fval <= MAX_CAVE_FLOOR))
  661.         for (i7 = m - 1; i7 <= m + 1; i7++)
  662.             for (i8 = n - 1; i8 <= n + 1; i8++) {
  663.             c_ptr = &cave[i7][i8];
  664.             if (c_ptr->fval >= MIN_CAVE_WALL)
  665.                 c_ptr->pl = TRUE;
  666.             else if ((c_ptr->tptr != 0) &&
  667.                  (t_list[c_ptr->tptr].tval >= TV_MIN_VISIBLE) &&
  668.                    (t_list[c_ptr->tptr].tval <= TV_MAX_VISIBLE))
  669.                 c_ptr->fm = TRUE;
  670.             }
  671.     prt_map();
  672. }
  673.  
  674.  
  675. /* Identify an object                    -RAK-     */
  676. int 
  677. ident_spell()
  678. {
  679.     int                 item_val;
  680.     bigvtype            out_val, tmp_str;
  681.     register int        ident;
  682.     register inven_type *i_ptr;
  683.  
  684.     ident = FALSE;
  685.     switch (get_item(&item_val, "Item you wish identified?", 0,
  686.              INVEN_ARRAY_SIZE, 0))
  687.     {
  688.     case TRUE:
  689.         ident = TRUE;
  690.         identify(&item_val);
  691.         i_ptr = &inventory[item_val];
  692.         known2(i_ptr);
  693.         objdes(tmp_str, i_ptr, TRUE);
  694.         if (item_val >= INVEN_WIELD) {
  695.         calc_bonuses();
  696.         
  697.         (void)sprintf(out_val, "%s: %s. ",
  698.                   describe_use(item_val), tmp_str);
  699.         }  else
  700.         (void)sprintf(out_val, "(%c) %s. ", item_val + 97, tmp_str);
  701.         msg_print(out_val);
  702.         break;
  703.     case FUZZY:
  704.         ident = TRUE;
  705.         i_ptr = &t_list[cave[char_row][char_col].tptr];
  706.         /* that piece of code taken from desc.c:identify()
  707.          * no use to convert type for calling identify since obj
  708.          * on floor can't stack
  709.          */
  710.  
  711.         if ((i_ptr->flags & TR_CURSED) && (i_ptr->tval != TV_MAGIC_BOOK) &&
  712.         (i_ptr->tval != TV_PRAYER_BOOK))
  713.         add_inscribe(i_ptr, ID_DAMD);
  714.         if (!known1_p(i_ptr))
  715.         known1(i_ptr);
  716.         /* end of identify-code */
  717.         known2(i_ptr);
  718.         objdes(tmp_str, i_ptr, TRUE);
  719.         (void) sprintf(out_val, "%c %s", item_val+97, tmp_str);
  720.         msg_print(out_val+2);
  721.         break;
  722.     default:
  723.         break;        
  724.     }
  725.     return (ident);
  726. }
  727.  
  728.  
  729. /* Get all the monsters on the level pissed off.    -RAK-     */
  730. int 
  731. aggravate_monster(dis_affect)
  732. int dis_affect;
  733. {
  734.     register int           i, aggravate;
  735.     register monster_type *m_ptr;
  736.  
  737.     aggravate = FALSE;
  738.     for (i = mfptr - 1; i >= MIN_MONIX; i--) {
  739.     m_ptr = &m_list[i];
  740.     m_ptr->csleep = 0;
  741.     if ((m_ptr->cdis <= dis_affect) && (m_ptr->cspeed < 2)) {
  742.         m_ptr->cspeed++;
  743.         aggravate = TRUE;
  744.     }
  745.     }
  746.     if (aggravate)
  747.     msg_print("You hear a sudden stirring in the distance!");
  748.     return (aggravate);
  749. }
  750.  
  751.  
  752. /* Surround the fool with traps (chuckle)        -RAK-     */
  753. int 
  754. trap_creation()
  755. {
  756.     register int        i, j, trap;
  757.     register cave_type *c_ptr;
  758.  
  759.     trap = FALSE;
  760.     for (i = char_row - 1; i <= char_row + 1; i++)
  761.     for (j = char_col - 1; j <= char_col + 1; j++) {
  762.         if ((i == char_row) && (j == char_col))
  763.         continue;       /* no trap under player, from um55 -CFT */
  764.         c_ptr = &cave[i][j];
  765.         if (c_ptr->fval <= MAX_CAVE_FLOOR) {
  766.         if ((c_ptr->tptr == 0) ||
  767.             ((t_list[c_ptr->tptr].tval != TV_UP_STAIR)
  768.              /* if not stairs or a store */
  769.              &&(t_list[c_ptr->tptr].tval != TV_DOWN_STAIR)
  770.              && (t_list[c_ptr->tptr].tval != TV_STORE_DOOR)) ||
  771.             (t_list[c_ptr->tptr].tval < TV_MIN_WEAR) ||
  772.             (t_list[c_ptr->tptr].tval > TV_MAX_WEAR) ||
  773.             !(t_list[c_ptr->tptr].flags2 & TR_ARTIFACT)) {
  774.                 /* if no artifact here -CFT */
  775.             trap = TRUE;
  776.             if (c_ptr->tptr != 0)
  777.             (void)delete_object(i, j);
  778.             place_trap(i, j, randint(MAX_TRAP) - 1);
  779.         /* don't let player gain exp from the newly created traps */
  780.             t_list[c_ptr->tptr].p1 = 0;
  781.         /* open pits are immediately visible, so call lite_spot */
  782.             lite_spot(i, j);
  783.         } else
  784.             msg_print("The object resists the spell.");
  785.         }
  786.     }
  787.     return (trap);
  788. }
  789.  
  790.  
  791. /* Destroys any adjacent door(s)/trap(s)        -RAK-     */
  792. int 
  793. td_destroy()
  794. {
  795.     register int        i, j, destroy;
  796.     register cave_type *c_ptr;
  797.  
  798.     destroy = FALSE;
  799.     for (i = char_row - 1; i <= char_row + 1; i++)
  800.     for (j = char_col - 1; j <= char_col + 1; j++) {
  801.         c_ptr = &cave[i][j];
  802.         if (c_ptr->tptr != 0) {
  803.         if (((t_list[c_ptr->tptr].tval >= TV_INVIS_TRAP) &&
  804.              (t_list[c_ptr->tptr].tval <= TV_CLOSED_DOOR) &&
  805.              (t_list[c_ptr->tptr].tval != TV_RUBBLE)) ||
  806.             (t_list[c_ptr->tptr].tval == TV_SECRET_DOOR)) {
  807.             if (delete_object(i, j))
  808.             destroy = TRUE;
  809.         } else if (t_list[c_ptr->tptr].tval == TV_CHEST) {
  810.         /* destroy traps on chest and unlock */
  811.             t_list[c_ptr->tptr].flags &= ~(CH_TRAPPED | CH_LOCKED);
  812.             t_list[c_ptr->tptr].name2 = SN_DISARMED;
  813.             msg_print("You have disarmed the chest.");
  814.             known2(&t_list[c_ptr->tptr]);
  815.             destroy = TRUE;
  816.         }
  817.         }
  818.     }
  819.     return (destroy);
  820. }
  821.  
  822.  
  823. /* Display all creatures on the current panel        -RAK-     */
  824. int 
  825. detect_monsters()
  826. {
  827.     register int        i, detect;
  828.     register monster_type *m_ptr;
  829.  
  830.     detect = FALSE;
  831.     for (i = mfptr - 1; i >= MIN_MONIX; i--) {
  832.     m_ptr = &m_list[i];
  833.     if (panel_contains((int)m_ptr->fy, (int)m_ptr->fx) &&
  834.         ((CM_INVISIBLE & c_list[m_ptr->mptr].cmove) == 0)) {
  835.         m_ptr->ml = TRUE;
  836.     /* works correctly even if hallucinating */
  837.         print((char)c_list[m_ptr->mptr].cchar, (int)m_ptr->fy,
  838.           (int)m_ptr->fx);
  839.         detect = TRUE;
  840.     }
  841.     }
  842.     if (detect) {
  843.     msg_print("You sense the presence of monsters!");
  844.     msg_print(NULL);
  845.     /* must unlight every monster just lighted */
  846.     creatures(FALSE);
  847.     }
  848.     return (detect);
  849. }
  850.  
  851.  
  852. /* Leave a line of light in given dir, blue light can sometimes     */
  853. /* hurt creatures.                       -RAK-   */
  854. void 
  855. light_line(dir, y, x)
  856. int dir, y, x;
  857. {
  858.     register cave_type *c_ptr;
  859.     int                 dist, flag;
  860.  
  861.     dist = (-1);
  862.     flag = FALSE;
  863.     do {
  864.     /* put mmove at end because want to light up current spot */
  865.     dist++;
  866.     c_ptr = &cave[y][x];
  867.     if ((dist > OBJ_BOLT_RANGE) || c_ptr->fval >= MIN_CLOSED_SPACE)
  868.         flag = TRUE;
  869.     if (!c_ptr->pl && !c_ptr->tl) {
  870.     /* set pl so that lite_spot will work */
  871.         c_ptr->pl = TRUE;
  872.         if (c_ptr->fval == LIGHT_FLOOR) {
  873.         if (panel_contains(y, x))
  874.             light_room(y, x);
  875.         } else
  876.         lite_spot(y, x);
  877.     }
  878.     /* set pl in case tl was true above */
  879.     c_ptr->pl = TRUE;
  880.     mon_light_dam(y, x, damroll(6, 8));
  881.     (void)mmove(dir, &y, &x);
  882.     }
  883.     while (!flag);
  884. }
  885.  
  886.  
  887. /* Light line in all directions                -RAK-     */
  888. void 
  889. starlite(y, x)
  890. register int y, x;
  891. {
  892.     register int i;
  893.  
  894.     if (py.flags.blind < 1)
  895.     msg_print("The end of the staff bursts into a blue shimmering light.");
  896.     for (i = 1; i <= 9; i++)
  897.     if (i != 5)
  898.         light_line(i, y, x);
  899. }
  900.  
  901. /* Disarms all traps/chests in a given direction    -RAK-     */
  902. int 
  903. disarm_all(dir, y, x)
  904. int dir, y, x;
  905. {
  906.     register cave_type  *c_ptr;
  907.     register inven_type *t_ptr;
  908.     register int         disarm, dist;
  909.  
  910.     disarm = FALSE;
  911.     dist = (-1);
  912.     do {
  913.     /* put mmove at end, in case standing on a trap */
  914.     dist++;
  915.     c_ptr = &cave[y][x];
  916.  
  917.     /* note, must continue upto and including the first non open space,
  918.      * because secret doors have fval greater than MAX_OPEN_SPACE 
  919.      */
  920.     if (c_ptr->tptr != 0) {
  921.         t_ptr = &t_list[c_ptr->tptr];
  922.         if ((t_ptr->tval == TV_INVIS_TRAP) || (t_ptr->tval == TV_VIS_TRAP)) {
  923.         if (delete_object(y, x))
  924.             disarm = TRUE;
  925.         } else if (t_ptr->tval == TV_CLOSED_DOOR)
  926.         t_ptr->p1 = 0;       /* Locked or jammed doors become merely closed. */
  927.         else if (t_ptr->tval == TV_SECRET_DOOR) {
  928.         c_ptr->fm = TRUE;
  929.         change_trap(y, x);
  930.         disarm = TRUE;
  931.         } else if ((t_ptr->tval == TV_CHEST) && (t_ptr->flags != 0)) {
  932.         msg_print("Click!");
  933.         t_ptr->flags &= ~(CH_TRAPPED | CH_LOCKED);
  934.         disarm = TRUE;
  935.         t_ptr->name2 = SN_UNLOCKED;
  936.         known2(t_ptr);
  937.         }
  938.     }
  939.     (void)mmove(dir, &y, &x);
  940.     }
  941.     while ((dist <= OBJ_BOLT_RANGE) && c_ptr->fval <= MAX_OPEN_SPACE);
  942.     return (disarm);
  943. }
  944.  
  945.  
  946. /* Shoot a bolt in a given direction            -RAK-     */
  947. void 
  948. fire_bolt(typ, dir, y, x, dam_hp)
  949. int typ, dir, y, x, dam_hp;
  950. {
  951.     int                 i, oldy, oldx, dist, flag;
  952. /*    int32u              harm_type = 0; */
  953.     register cave_type *c_ptr;
  954.     register monster_type *m_ptr;
  955.     register creature_type *r_ptr;
  956.     vtype               out_val, m_name;
  957.     int                 dam = dam_hp;
  958.     int                 ny, nx;
  959.     char                bolt_char;
  960.  
  961.     flag = FALSE;
  962.     oldy = y;
  963.     oldx = x;
  964.     dist = 0;
  965.     do {
  966.     ny = y;
  967.     nx = x;
  968.     (void)mmove(dir, &y, &x);
  969.     /* choose the right shape for the bolt... -CFT */
  970.     if (ny == y)
  971.         bolt_char = '-';
  972.     else if (nx == x)
  973.         bolt_char = '|';
  974.     else if ((ny - y) == (nx - x))
  975.         bolt_char = '\\';
  976.     else
  977.         bolt_char = '/';
  978.  
  979.     dist++;
  980.     c_ptr = &cave[y][x];
  981.     lite_spot(oldy, oldx);
  982.     if ((dist > OBJ_BOLT_RANGE) || c_ptr->fval >= MIN_CLOSED_SPACE)
  983.         flag = TRUE;
  984.     else {
  985.         if (c_ptr->cptr > 1) {
  986.         flag = TRUE;
  987.         m_ptr = &m_list[c_ptr->cptr];
  988.         r_ptr = &c_list[m_ptr->mptr];
  989.         /*
  990.          * light up monster and draw monster, temporarily set pl so that
  991.          * update_mon() will work 
  992.          */
  993.         i = c_ptr->pl;
  994.         c_ptr->pl = TRUE;
  995.         update_mon((int)c_ptr->cptr);
  996.         c_ptr->pl = i;
  997.         /* draw monster and clear previous bolt */
  998.         put_qio();
  999.  
  1000.         spell_hit_monster(m_ptr, typ, &dam, 0, &ny, &nx, TRUE);
  1001.         c_ptr = &cave[ny][nx];    /* may be new location if teleported
  1002.                      * by gravity warp... */
  1003.         m_ptr = &m_list[c_ptr->cptr];    /* and even if not, may be
  1004.                          * new monster if chaos
  1005.                          * polymorphed */
  1006.         r_ptr = &c_list[m_ptr->mptr];
  1007.         monster_name(m_name, m_ptr, r_ptr);
  1008.  
  1009.         if ((dam > 0) && (m_ptr->hp >= dam)) {
  1010.             (void)sprintf(out_val,
  1011.                    pain_message((int)c_ptr->cptr, dam), m_name);
  1012.             msg_print(out_val);
  1013.         }
  1014.  
  1015.         i = mon_take_hit((int)c_ptr->cptr, dam, TRUE);
  1016.  
  1017.         if (i >= 0)
  1018.             prt_experience();
  1019.  
  1020.         } else if (panel_contains(y, x) && (py.flags.blind < 1)) {
  1021.         print(bolt_char, y, x);
  1022.         /* show the bolt */
  1023.         put_qio();
  1024. #ifdef MSDOS
  1025.         delay(8 * delay_spd);    /* milliseconds */
  1026. #else
  1027.         usleep(8000 * delay_spd);    /* useconds */
  1028. #endif
  1029.         }
  1030.     }
  1031.     oldy = y;
  1032.     oldx = x;
  1033. #ifdef TARGET
  1034.     if (target_mode && at_target(y,x))
  1035.         flag = TRUE; /* must have hit "targeted" area -CFT */
  1036. #endif
  1037.     }
  1038.     while (!flag);
  1039.     lite_spot(oldy, oldx);       /* just in case, clear any leftover bolt images -CFT */
  1040. }
  1041.  
  1042.  
  1043. /* Shoot a bolt in a given direction                    -RAK-   */
  1044. /* heavily modified to include exotic bolts -CFT */
  1045. void 
  1046. bolt(typ, y, x, dam_hp, ddesc, ptr, monptr)
  1047. int           typ, y, x, dam_hp;
  1048. char         *ddesc;
  1049. monster_type *ptr;
  1050. int           monptr;
  1051. {
  1052.     int                 i = ptr->fy, j = ptr->fx;
  1053.     int                 dam;
  1054.     int32u              tmp, treas;
  1055.     register cave_type     *c_ptr;
  1056.     register monster_type  *m_ptr;
  1057.     register creature_type *r_ptr;
  1058.     char                bolt_char;
  1059.     int                 blind = (py.flags.status & PY_BLIND) ? 1 : 0;
  1060.     int                 ny, nx, sourcey, sourcex, dist;
  1061.     vtype               m_name, out_val;
  1062.  
  1063.     sourcey = i;
  1064.     sourcex = j;
  1065.     dist = 0;
  1066.     do {
  1067.     /* This is going along a badly angled line so call mmove2 direct */
  1068.     ny = i;
  1069.     nx = j;
  1070.     mmove2(&i, &j, sourcey, sourcex, char_row, char_col);
  1071.     dist++;
  1072.  
  1073.     /* choose the right shape for the bolt... -CFT */
  1074.     if (ny == i)
  1075.         bolt_char = '-';
  1076.     else if (nx == j)
  1077.         bolt_char = '|';
  1078.     else if ((ny - i) == (nx - j))
  1079.         bolt_char = '\\';
  1080.     else
  1081.         bolt_char = '/';
  1082.  
  1083.     if (in_bounds(i, j) && los(y, x, i, j)) {
  1084.         c_ptr = &cave[i][j];
  1085.         if (c_ptr->fval <= MAX_OPEN_SPACE) {
  1086.         if (panel_contains(i, j) && !(py.flags.status & PY_BLIND)) {
  1087.             print(bolt_char, i, j);
  1088.             put_qio();
  1089. #ifdef MSDOS
  1090.             delay(8 * delay_spd);    /* milliseconds */
  1091. #else
  1092.             usleep(8000 * delay_spd);    /* useconds */
  1093. #endif
  1094.             lite_spot(i, j);
  1095.         }
  1096.         if (c_ptr->cptr > 1 && c_ptr->cptr != monptr) {
  1097.             m_ptr = &m_list[c_ptr->cptr];
  1098.             dam = dam_hp;
  1099.  
  1100.             spell_hit_monster(m_ptr, typ, &dam, 0, &ny, &nx, FALSE);
  1101.                 /* process hit effects */
  1102.             /* may be new location if teleported by gravity warp... */
  1103.             c_ptr = &cave[ny][nx];
  1104.             /* and even if not, may be new monster if chaos polymorphed */
  1105.             m_ptr = &m_list[c_ptr->cptr];
  1106.             r_ptr = &c_list[m_ptr->mptr];
  1107.             monster_name(m_name, m_ptr, r_ptr);
  1108.  
  1109.             if (dam < 1)
  1110.             dam = 1;   /* protect vs neg damage -CFT */
  1111.             m_ptr->hp = m_ptr->hp - dam;
  1112.             m_ptr->csleep = 0;
  1113.  
  1114. /* prevent unique monster from death by other monsters.  It causes trouble
  1115.  * (monster not marked as dead, quest monsters don't satisfy quest, etc).
  1116.  * So, we let them live, but extremely wimpy. -CFT
  1117.  */
  1118.             if ((r_ptr->cdefense & UNIQUE) && (m_ptr->hp < 0))
  1119.             m_ptr->hp = 0;
  1120.  
  1121.             if (m_ptr->hp < 0) {
  1122.             object_level = (dun_level + r_ptr->level) >> 1;
  1123.             coin_type = 0;
  1124.             get_coin_type(r_ptr);
  1125.             treas = monster_death((int)m_ptr->fy, (int)m_ptr->fx,
  1126.                           r_ptr->cmove, 0, 0);
  1127.             coin_type = 0;
  1128.             if (m_ptr->ml || (c_list[m_ptr->mptr].cdefense & UNIQUE)) {
  1129.                 tmp = (c_recall[m_ptr->mptr].r_cmove & CM_TREASURE)
  1130.                 >> CM_TR_SHIFT;
  1131.                 if (tmp > ((treas & CM_TREASURE) >> CM_TR_SHIFT))
  1132.                 treas = (treas & ~CM_TREASURE) | (tmp << CM_TR_SHIFT);
  1133.                 c_recall[m_ptr->mptr].r_cmove = treas |
  1134.                 (c_recall[m_ptr->mptr].r_cmove & ~CM_TREASURE);
  1135.             }
  1136.             if (monptr < c_ptr->cptr)
  1137.                 delete_monster((int)c_ptr->cptr);
  1138.             else
  1139.                 fix1_delete_monster((int)c_ptr->cptr);
  1140.             } else {
  1141.             (void)sprintf(out_val, pain_message((int)c_ptr->cptr, dam),
  1142.                       m_name);
  1143.             msg_print(out_val);
  1144.             }
  1145.             break;
  1146.         } else if (c_ptr->cptr == 1) {
  1147.             if (dam_hp < 1)
  1148.             dam_hp = 1;
  1149.             m_ptr = &m_list[monptr];
  1150.             switch (typ) {
  1151.               case GF_LIGHTNING:
  1152.             if (blind)
  1153.                 msg_print("You are hit by electricity!");
  1154.             light_dam(dam_hp, ddesc);
  1155.             break;
  1156.               case GF_POISON_GAS:
  1157.             if (blind)
  1158.                 msg_print("You are hit by a blast of noxious gases!");
  1159.             poison_gas(dam_hp, ddesc);
  1160.             break;
  1161.               case GF_ACID:
  1162.             if (blind)
  1163.                 msg_print("You are hit by a jet of acidic fluid!");
  1164.             acid_dam(dam_hp, ddesc);
  1165.             break;
  1166.               case GF_FROST:
  1167.             if (blind)
  1168.                 msg_print("You are hit by something cold!");
  1169.             cold_dam(dam_hp, ddesc);
  1170.             break;
  1171.               case GF_FIRE:
  1172.             if (blind)
  1173.                 msg_print("You are hit by something hot!");
  1174.             fire_dam(dam_hp, ddesc);
  1175.             break;
  1176.               case GF_MAGIC_MISSILE:
  1177.             if (blind)
  1178.                 msg_print("You are hit by something!");
  1179.             take_hit(dam_hp, ddesc);
  1180.             break;
  1181.               case GF_HOLY_ORB:
  1182.             if (blind)
  1183.                 msg_print("You are hit by something!");
  1184.             dam_hp /= 2;    /* player should take less damage
  1185.                      * -CFT */
  1186.             take_hit(dam_hp, ddesc);
  1187.             break;
  1188.               case GF_ARROW:    /* maybe can miss? */
  1189.             if (blind)
  1190.                 msg_print("You are hit by something!");
  1191.             take_hit(dam_hp, ddesc);
  1192.             break;
  1193.               case GF_PLASMA:    /* no resist to plasma? */
  1194.             if (blind)
  1195.                 msg_print("You are hit by something!");
  1196.             take_hit(dam_hp, ddesc);
  1197.             break;
  1198.               case GF_NETHER:
  1199.             if (blind)
  1200.                 msg_print("You are hit by an unholy blast!");
  1201.             if (py.flags.nether_resist) {
  1202.                 dam_hp *= 6;    /* these 2 lines give avg dam
  1203.                          * of .655, ranging from */
  1204.                 dam_hp /= (randint(6) + 6);    /* .858 to .5 -CFT */
  1205.             } else {   /* no resist */
  1206.                 if (py.flags.hold_life && randint(5) > 1)
  1207.                 msg_print("You keep hold of your life force!");
  1208.                 else if (py.flags.hold_life) {
  1209.                 msg_print("You feel your life slipping away!");
  1210.                 lose_exp(200 + (py.misc.exp / 1000) * MON_DRAIN_LIFE);
  1211.                 } else {
  1212.                 msg_print("You feel your life draining away!");
  1213.                 lose_exp(200 + (py.misc.exp / 100) * MON_DRAIN_LIFE);
  1214.                 }
  1215.             }
  1216.             take_hit(dam_hp, ddesc);
  1217.             break;
  1218.               case GF_WATER:
  1219.             if (blind)
  1220.                 msg_print("You are hit by a jet of water!");
  1221.             if (!py.flags.sound_resist)
  1222.                 stun_player(randint(15));
  1223.             take_hit(dam_hp, ddesc);
  1224.             break;
  1225.               case GF_CHAOS:
  1226.             if (blind)
  1227.                 msg_print("You are hit by wave of entropy!");
  1228.             if (py.flags.chaos_resist) {
  1229.                 dam_hp *= 6;    /* these 2 lines give avg dam
  1230.                          * of .655, ranging from */
  1231.                 dam_hp /= (randint(6) + 6);    /* .858 to .5 -CFT */
  1232.             }
  1233.             if ((!py.flags.confusion_resist) && (!py.flags.chaos_resist)) {
  1234.                 if (py.flags.confused > 0)
  1235.                 py.flags.confused += 12;
  1236.                 else
  1237.                 py.flags.confused = randint(20) + 10;
  1238.             }
  1239.             if (!py.flags.chaos_resist)
  1240.                 py.flags.image += randint(10);
  1241.             take_hit(dam_hp, ddesc);
  1242.             break;
  1243.               case GF_SHARDS:
  1244.             if (blind)
  1245.                 msg_print("You are cut by sharp fragments!");
  1246.             if (py.flags.shards_resist) {
  1247.                 dam_hp *= 6;    /* these 2 lines give avg dam
  1248.                          * of .655, ranging from */
  1249.                 dam_hp /= (randint(6) + 6);    /* .858 to .5 -CFT */
  1250.             } else {
  1251.                 cut_player(dam_hp);    /* ouch! */
  1252.             }
  1253.             take_hit(dam_hp, ddesc);
  1254.             break;
  1255.               case GF_SOUND:
  1256.             if (blind)
  1257.                 msg_print("You are deafened by a blast of noise!");
  1258.             if (py.flags.sound_resist) {
  1259.                 dam_hp *= 5;
  1260.                 dam_hp /= (randint(6) + 6);
  1261.             } else {
  1262.                 stun_player(randint((dam_hp > 60) ? 25 : (dam_hp / 3 + 5)));
  1263.             }
  1264.             take_hit(dam_hp, ddesc);
  1265.             break;
  1266.               case GF_CONFUSION:
  1267.             if (blind)
  1268.                 msg_print("You are hit by a wave of dizziness!");
  1269.             if (py.flags.confusion_resist) {
  1270.                 dam_hp *= 5;
  1271.                 dam_hp /= (randint(6) + 6);
  1272.             }
  1273.             if (!py.flags.confusion_resist && !py.flags.chaos_resist) {
  1274.                 if (py.flags.confused > 0)
  1275.                 py.flags.confused += 8;
  1276.                 else
  1277.                 py.flags.confused = randint(15) + 5;
  1278.             }
  1279.             take_hit(dam_hp, ddesc);
  1280.             break;
  1281.               case GF_DISENCHANT:
  1282.             if (blind)
  1283.                 msg_print("You are hit by something!");
  1284.             if (py.flags.disenchant_resist) {
  1285.                 dam_hp *= 6;    /* these 2 lines give avg dam
  1286.                          * of .655, ranging from */
  1287.                 dam_hp /= (randint(6) + 6);    /* .858 to .5 -CFT */
  1288.             } else {
  1289.                 int8u               disenchant = FALSE;
  1290.                 int8u               chance;
  1291.                 int                 t = 0;
  1292.                 inven_type         *i_ptr;
  1293.  
  1294.                 switch (randint(7)) {
  1295.                   case 1:
  1296.                 t = INVEN_BODY;
  1297.                 break;
  1298.                   case 2:
  1299.                 t = INVEN_BODY;
  1300.                 break;
  1301.                   case 3:
  1302.                 t = INVEN_ARM;
  1303.                 break;
  1304.                   case 4:
  1305.                 t = INVEN_OUTER;
  1306.                 break;
  1307.                   case 5:
  1308.                 t = INVEN_HANDS;
  1309.                 break;
  1310.                   case 6:
  1311.                 t = INVEN_HEAD;
  1312.                 break;
  1313.                   case 7:
  1314.                 t = INVEN_FEET;
  1315.                 break;
  1316.                 }
  1317.                 i_ptr = &inventory[t];
  1318.                 chance = 1;
  1319.                 if (i_ptr->flags2 & TR_ARTIFACT)    /* Artifacts have 2/3 */
  1320.                 chance = randint(3);    /* chance to resist -DGK */
  1321.                 if ((i_ptr->tohit > 0) && (chance == 1)) {
  1322.                 i_ptr->tohit -= randint(2);
  1323.                 /* don't send it below zero */
  1324.                 if (i_ptr->tohit < 0)
  1325.                     i_ptr->tohit = 0;
  1326.                 disenchant = TRUE;
  1327.                 }
  1328.                 if ((i_ptr->todam > 0) && (chance == 1)) {
  1329.                 i_ptr->todam -= randint(2);
  1330.                 /* don't send it below zero */
  1331.                 if (i_ptr->todam < 0)
  1332.                     i_ptr->todam = 0;
  1333.                 disenchant = TRUE;
  1334.                 }
  1335.                 if ((i_ptr->toac > 0) && (chance == 1)) {
  1336.                 i_ptr->toac -= randint(2);
  1337.                 /* don't send it below zero */
  1338.                 if (i_ptr->toac < 0)
  1339.                     i_ptr->toac = 0;
  1340.                 disenchant = TRUE;
  1341.                 }
  1342.                 if (disenchant || (chance != 1)) {
  1343.                 vtype               t1, t2;
  1344.  
  1345.                 objdes(t1, &inventory[t], FALSE);
  1346.                 if (chance != 1)
  1347.                     sprintf(t2, "Your %s (%c) %s disenchanted!", t1,
  1348.                         i + 'a' - INVEN_WIELD,
  1349.                         (inventory[i].number != 1) ? "were" : "was");
  1350.                 else
  1351.                     sprintf(t2, "Your %s (%c) %s disenchantment!", t1,
  1352.                         i + 'a' - INVEN_WIELD,
  1353.                         (inventory[i].number != 1) ?
  1354.                         "resist" : "resists");
  1355.                 msg_print(t2);
  1356.                 calc_bonuses();
  1357.                 }
  1358.             }
  1359.             take_hit(dam_hp, ddesc);
  1360.             break;
  1361. /* no spec. effects from nexus bolt, only breath -CFT */
  1362.               case GF_NEXUS:
  1363.             if (blind)
  1364.                 msg_print("You are hit by something strange!");
  1365.             if (py.flags.nexus_resist) {
  1366.                 dam_hp *= 6;    /* these 2 lines give avg dam
  1367.                          * of .655, ranging from */
  1368.                 dam_hp /= (randint(6) + 6);    /* .858 to .5 -CFT */
  1369.             }
  1370.             take_hit(dam_hp, ddesc);
  1371.             break;
  1372.               case GF_FORCE:
  1373.             if (blind)
  1374.                 msg_print("You are hit hard by a sudden force!");
  1375.             if (!py.flags.sound_resist)
  1376.                 stun_player(randint(15) + 1);
  1377.             take_hit(dam_hp, ddesc);
  1378.             break;
  1379.               case GF_INERTIA:
  1380.             if (blind)
  1381.                 msg_print("You are hit by something!");
  1382.             if ((py.flags.slow > 0) && (py.flags.slow < 32000))
  1383.                 py.flags.slow += randint(5);
  1384.             else {
  1385.                 msg_print("You feel less able to move.");
  1386.                 py.flags.slow = randint(5) + 3;
  1387.             }
  1388.             take_hit(dam_hp, ddesc);
  1389.             break;
  1390.               case GF_LIGHT:
  1391.             if (blind)
  1392.                 msg_print("You are hit by something!");
  1393.             if (py.flags.light_resist) {
  1394.                 dam_hp *= 4;    /* these 2 lines give avg dam
  1395.                          * of .444, ranging from */
  1396.                 dam_hp /= (randint(6) + 6);    /* .556 to .333 -CFT */
  1397.             } else if (!blind && !py.flags.blindness_resist) {
  1398.                 msg_print("You are blinded by the flash!");
  1399.                 py.flags.blind += randint(5) + 2;
  1400.             }
  1401.             take_hit(dam_hp, ddesc);
  1402.             break;
  1403.               case GF_DARK:
  1404.             if (blind)
  1405.                 msg_print("You are hit by something!");
  1406.             if (py.flags.dark_resist) {
  1407.                 dam_hp *= 4;    /* these 2 lines give avg dam
  1408.                          * of .444, ranging from */
  1409.                 dam_hp /= (randint(6) + 6);    /* .556 to .333 -CFT */
  1410.             } else {
  1411.                 if (!blind && !py.flags.blindness_resist) {
  1412.                 msg_print("The darkness prevents you from seeing!");
  1413.                 py.flags.blind += randint(5) + 2;
  1414.                 }
  1415.             }
  1416.             take_hit(dam_hp, ddesc);
  1417.             break;
  1418.               case GF_TIME:    /* only some effects from time bolt
  1419.                      * -CFT */
  1420.             if (blind)
  1421.                 msg_print("You are hit by something!");
  1422.             if (randint(2) == 1) {
  1423.                 msg_print("You feel life has clocked back.");
  1424.                 lose_exp(m_ptr->hp + (py.misc.exp / 300) * MON_DRAIN_LIFE);
  1425.             } else {
  1426.                 int                 t = 0;
  1427.  
  1428.                 switch (randint(6)) {
  1429.                   case 1:
  1430.                 t = A_STR;
  1431.                 msg_print("You're not as strong as you used to be...");
  1432.                 break;
  1433.                   case 2:
  1434.                 t = A_INT;
  1435.                 msg_print("You're not as bright as you used to be...");
  1436.                 break;
  1437.                   case 3:
  1438.                 t = A_WIS;
  1439.                 msg_print("You're not as wise as you used to be...");
  1440.                 break;
  1441.                   case 4:
  1442.                 t = A_DEX;
  1443.                 msg_print("You're not as agile as you used to be...");
  1444.                 break;
  1445.                   case 5:
  1446.                 t = A_CON;
  1447.                 msg_print("You're not as hale as you used to be...");
  1448.                 break;
  1449.                   case 6:
  1450.                 t = A_CHR;
  1451.                 msg_print("You're not as beautiful as you used to be...");
  1452.                 break;
  1453.                 }
  1454.                 py.stats.cur_stat[t] = (py.stats.cur_stat[t] * 3) / 4;
  1455.                 if (py.stats.cur_stat[t] < 3)
  1456.                 py.stats.cur_stat[t] = 3;
  1457.                 set_use_stat(t);
  1458.                 prt_stat(t);
  1459.             }
  1460.             take_hit(dam_hp, ddesc);
  1461.             break;
  1462.               case GF_GRAVITY:
  1463.             if (blind)
  1464.                 msg_print("You are hit by a surge of gravity!");
  1465.             if ((!py.flags.sound_resist) && (!py.flags.ffall))    /* DGK */
  1466.                 stun_player(randint(15) + 1);
  1467.             if (py.flags.ffall) {    /* DGK */
  1468.                 dam_hp *= 3;    /* these 2 lines give avg dam
  1469.                          * of .25, ranging from */
  1470.                 dam_hp /= (randint(6) + 6);    /* .427 to .25 -CFT */
  1471.             } else {   /* DGK */
  1472.                 if ((py.flags.slow > 0) && (py.flags.slow < 32000))
  1473.                 py.flags.slow += randint(5);
  1474.                 else {
  1475.                 msg_print("You feel less able to move.");
  1476.                 py.flags.slow = randint(5) + 3;
  1477.                 }
  1478.             } /* DGK */
  1479.             take_hit(dam_hp, ddesc);
  1480.             break;
  1481.               case GF_MANA:
  1482.             if (blind)
  1483.                 msg_print("You are hit by a beam of power!");
  1484.             take_hit(dam_hp, ddesc);
  1485.             break;
  1486.               case GF_METEOR:
  1487.             if (blind)
  1488.                 msg_print("You are hit by something!");
  1489.             take_hit(dam_hp, ddesc);
  1490.             break;
  1491.               case GF_ICE:
  1492.             if (blind)
  1493.                 msg_print("You are hit by something cold and sharp!");
  1494.             cold_dam(dam_hp, ddesc);
  1495.             if (!py.flags.sound_resist)
  1496.                 stun_player(randint(15) + 1);
  1497.             if (!py.flags.shards_resist)
  1498.                 cut_player(damroll(8, 10));
  1499.             break;
  1500.               default:
  1501.             msg_print("Unknown typ in bolt().  This may mean trouble.");
  1502.             }
  1503.             disturb(1, 0);
  1504.             break;
  1505.         }
  1506.         }
  1507.     }
  1508.     } while ((i != char_row) || (j != char_col));
  1509. }
  1510.  
  1511. /* Shoot a ball in a given direction.  Note that balls have an  */
  1512. /* area affect.                                       -RAK-   */
  1513. void 
  1514. fire_ball(typ, dir, y, x, dam_hp, max_dis)
  1515. int typ, dir, y, x, dam_hp, max_dis;
  1516. {
  1517.     register int        i, j;
  1518.     int                 dam, thit, tkill, k, tmp, monptr;
  1519.     int                 oldy, oldx, dist, flag;
  1520.     int                 (*destroy) ();
  1521.     register cave_type *c_ptr;
  1522.     register monster_type *m_ptr;
  1523.     register creature_type *r_ptr;
  1524.     int                 ny, nx;
  1525.     char                bolt_char;
  1526.  
  1527.     thit = 0;
  1528.     tkill = 0;
  1529.  
  1530.     ball_destroy(typ, &destroy);
  1531.  
  1532.     flag = FALSE;
  1533.     oldy = y;
  1534.     oldx = x;
  1535.     dist = 0;
  1536.     do {
  1537.     ny = y;
  1538.     nx = x;
  1539.  
  1540. /* we don't call mmove if targetting and at target.  This allow player to target
  1541.  * a ball spell at his position, to explode it around himself -CFT
  1542.  */
  1543.     if (dir || !at_target(y,x))        
  1544.         (void)mmove(dir, &y, &x);
  1545.  
  1546.     /* choose the right shape for the bolt... -CFT */
  1547.     if (ny == y)
  1548.         bolt_char = '-';
  1549.     else if (nx == x)
  1550.         bolt_char = '|';
  1551.     else if ((ny - y) == (nx - x))
  1552.         bolt_char = '\\';
  1553.     else
  1554.         bolt_char = '/';
  1555.  
  1556.     dist++;
  1557.     lite_spot(oldy, oldx);
  1558.     if (dist > OBJ_BOLT_RANGE)
  1559.         flag = TRUE;
  1560.     else {
  1561.         c_ptr = &cave[y][x];
  1562.     /* targeting code stolen from Morgul -CFT */
  1563.  
  1564.     /* This test has been overhauled (twice):  basically, it now says: if
  1565.      * ((spell hits a wall) OR ((spell hits a creature) and ((not
  1566.      * targetting) or (at the target anyway) or (no line-of-sight to
  1567.      * target, so aiming unusable) or ((aiming at a monster) and (that
  1568.      * monster is unseen, so aiming unusable)))) OR ((we are targetting)
  1569.      * and (at the target location))) THEN the ball explodes... -CFT  
  1570.      */
  1571.  
  1572. #ifndef TARGET
  1573.         if ((c_ptr->fval >= MIN_CLOSED_SPACE) ||
  1574.         ((c_ptr->cptr > 1))) {
  1575.         flag = TRUE;       /* THEN we decide to explode here. -CFT */
  1576.         if (c_ptr->fval >= MIN_CLOSED_SPACE) {
  1577.             y = oldy;
  1578.             x = oldx;
  1579.         }
  1580. #else
  1581.         if ((c_ptr->fval >= MIN_CLOSED_SPACE) ||
  1582.         ((c_ptr->cptr > 1) &&
  1583.          (!target_mode || at_target(y, x) ||
  1584.           !los(target_row, target_col, char_row, char_col) ||
  1585.           ((target_mon < MAX_MALLOC) && !m_list[target_mon].ml))) ||
  1586.         (target_mode && at_target(y, x))) {
  1587.             flag = TRUE;       /* THEN we decide to explode here. -CFT */
  1588.             if (c_ptr->fval >= MIN_CLOSED_SPACE) {
  1589.             y = oldy;
  1590.             x = oldx;
  1591.             }
  1592. #endif
  1593.         /* The ball hits and explodes.               */
  1594.         /* The explosion.                            */
  1595.         for (i = y - max_dis; i <= y + max_dis; i++)
  1596.             for (j = x - max_dis; j <= x + max_dis; j++)
  1597.             if (in_bounds(i, j) && (distance(y, x, i, j) <= max_dis) &&
  1598.              los(char_row, char_col, i, j) && los(y, x, i, j) &&
  1599.                 (cave[i][j].fval <= MAX_OPEN_SPACE) &&
  1600.                 panel_contains(i, j) && (py.flags.blind < 1)) {
  1601. #ifdef TC_COLOR
  1602.                 if (!no_color_flag)
  1603.                 textcolor(bolt_color(typ));
  1604. #endif
  1605.                 print('*', i, j);
  1606. #ifdef TC_COLOR
  1607.                 /* prob don't need here, but... -CFT */
  1608.                 if (!no_color_flag)
  1609.                 textcolor(LIGHTGRAY);
  1610. #endif
  1611.             }
  1612.         if (py.flags.blind < 1) {
  1613.             put_qio();
  1614. #ifdef MSDOS
  1615.             delay(25 * delay_spd);    /* milliseconds */
  1616. #else
  1617.             usleep(25000 * delay_spd);    /* useconds */
  1618. #endif
  1619.         }
  1620.  
  1621.         /* now erase the ball, since effects below may use msg_print, and
  1622.          * pause indefinitely, so we want ball gone before then -CFT 
  1623.          */
  1624.         for (i = y - max_dis; i <= y + max_dis; i++)
  1625.             for (j = x - max_dis; j <= x + max_dis; j++)
  1626.             if (in_bounds(i, j) && (distance(y, x, i, j) <= max_dis) &&
  1627.              los(char_row, char_col, i, j) && los(y, x, i, j) &&
  1628.                 (cave[i][j].fval <= MAX_OPEN_SPACE) &&
  1629.                 panel_contains(i, j) && (py.flags.blind < 1)) {
  1630.                 lite_spot(i, j);    /* draw what is below the '*' */
  1631.             }
  1632.         put_qio();
  1633.  
  1634.         /* First go over the area of effect, and destroy items...  Any
  1635.          * preexisting items will be affected, but items dropped by
  1636.          * killed monsters are assummed to have been "shielded" from the
  1637.          * effects the the monster's corpse.  This means that you no
  1638.          * longer have to be SO paranoid about using fire/frost/acid
  1639.          * balls. -CFT 
  1640.          */
  1641.         for (i = y - max_dis; i <= y + max_dis; i++)
  1642.             for (j = x - max_dis; j <= x + max_dis; j++)
  1643.             if (in_bounds(i, j) && (distance(y, x, i, j) <= max_dis)
  1644.                 && los(y, x, i, j) && (cave[i][j].tptr != 0) &&
  1645.                 (*destroy) (&t_list[cave[i][j].tptr]))
  1646.                 (void)delete_object(i, j);
  1647.         /* burn/corrode or OW destroy items in area of effect */
  1648.         /* now go over area of affect and DO something to monsters... */
  1649.         for (i = y - max_dis; i <= y + max_dis; i++)
  1650.             for (j = x - max_dis; j <= x + max_dis; j++)
  1651.             if (in_bounds(i, j) && (distance(y, x, i, j) <= max_dis)
  1652.                 && los(y, x, i, j)) {
  1653.                 c_ptr = &cave[i][j];
  1654.                 if (c_ptr->fval <= MAX_OPEN_SPACE) {
  1655.                 if (c_ptr->cptr > 1) {
  1656.                     dam = dam_hp;
  1657.                     m_ptr = &m_list[c_ptr->cptr];
  1658.                     spell_hit_monster(m_ptr, typ, &dam,
  1659.                       (distance(i, j, y, x) + 1), &ny, &nx, TRUE);
  1660.                     c_ptr = &cave[ny][nx];
  1661.             /* may be new location if teleported by gravity warp... */
  1662.                     m_ptr = &m_list[c_ptr->cptr];
  1663.             /* and even if not, may be new monster if chaos polymorphed */
  1664.                     r_ptr = &c_list[m_ptr->mptr];
  1665.                     monptr = c_ptr->cptr;
  1666.  
  1667.                 /*
  1668.                  * lite up creature if visible, temp set pl
  1669.                  * so that update_mon works 
  1670.                  */
  1671.                     tmp = c_ptr->pl;
  1672.                     c_ptr->pl = TRUE;
  1673.                     update_mon((int)c_ptr->cptr);
  1674.  
  1675.                     thit++;
  1676.                     if (dam < 1)
  1677.                     dam = 1;    /* protect vs neg damage -CFT */
  1678.                     k = mon_take_hit((int)c_ptr->cptr, dam, TRUE);
  1679.                     if (k >= 0)
  1680.                     tkill++;
  1681.                     c_ptr->pl = tmp;
  1682.                 }
  1683.                 lite_spot(i, j);    /* erase the ball... */
  1684.                 }
  1685.             }
  1686.         /* show ball of whatever */
  1687.         put_qio();
  1688.  
  1689.         /* End  explosion.                   */
  1690.         if (tkill == 1) {
  1691.             msg_print("There is a scream of agony!");
  1692.         } else if (tkill > 1) {
  1693.             msg_print("There are several screams of agony!");
  1694.         }
  1695.         if (tkill >= 0)
  1696.             prt_experience();
  1697.         /* End ball hitting.                 */
  1698.         } else if (panel_contains(y, x) && (py.flags.blind < 1)) {
  1699. #ifdef TC_COLOR
  1700.         if (!no_color_flag)
  1701.             textcolor(bolt_color(typ));
  1702. #endif
  1703.         print(bolt_char, y, x);
  1704.         put_qio();
  1705. #ifdef TC_COLOR
  1706.         if (!no_color_flag)
  1707.             textcolor(LIGHTGRAY);
  1708. #endif
  1709. #ifdef MSDOS
  1710.         delay(8 * delay_spd);    /* milliseconds */
  1711. #else
  1712.         usleep(8000 * delay_spd);    /* useconds */
  1713. #endif
  1714.         }
  1715.         oldy = y;
  1716.         oldx = x;
  1717. #ifdef TARGET
  1718.         if (target_mode && at_target(y,x))
  1719.         flag = TRUE; /* must have hit "targetted" area -CFT */
  1720. #endif
  1721.     }
  1722.     } while (!flag);
  1723. }
  1724.  
  1725. /* Lightning ball in all directions                        SM   */
  1726. void 
  1727. starball(y, x)
  1728.     register int        y, x;
  1729. {
  1730.     register int        i;
  1731.  
  1732.     for (i = 1; i <= 9; i++)
  1733.     if (i != 5)
  1734.         fire_ball(GF_LIGHTNING, i, y, x, 150, 3);
  1735. }
  1736.  
  1737. /* Breath weapon works like a fire_ball, but affects the player. */
  1738. /* Note the area affect.                              -RAK-   */
  1739. void 
  1740. breath(typ, y, x, dam_hp, ddesc, monptr)
  1741. int   typ, y, x, dam_hp;
  1742. char *ddesc;
  1743. int   monptr;
  1744. {
  1745.     register int        i, j;
  1746.     int                 dam, max_dis;
  1747.     int32u              tmp, treas;
  1748.     int                 (*destroy) ();
  1749.     register cave_type     *c_ptr;
  1750.     register monster_type  *m_ptr;
  1751.     register creature_type *r_ptr;
  1752.     int                 ny, nx;
  1753.     int                 blind = (py.flags.status & PY_BLIND) ? 1 : 0;
  1754.     char                ch;
  1755.  
  1756.     m_ptr = &m_list[monptr];
  1757.     r_ptr = &c_list[m_ptr->mptr];
  1758.     ch = r_ptr->cchar;
  1759.     if ((ch == 'v' || ch == 'D' || ch == 'E' || ch == '&' || ch == 'A') ||
  1760.     ((ch == 'd' || ch == 'R') && r_ptr->cdefense & UNIQUE))
  1761.     max_dis = 3;
  1762.     else
  1763.     max_dis = 2;
  1764.  
  1765.     ball_destroy(typ, &destroy);
  1766.  
  1767.     if (!(py.flags.status & PY_BLIND)) { /* only bother if the player can see */
  1768.     for (i = y - max_dis; i <= y + max_dis; i++)
  1769.         for (j = x - max_dis; j <= x + max_dis; j++)
  1770.         if (in_bounds(i, j) && (distance(y, x, i, j) <= max_dis) &&
  1771.             los(y, x, i, j) && (cave[i][j].fval <= MAX_OPEN_SPACE) &&
  1772.             panel_contains(i, j)) {
  1773. #ifdef TC_COLOR
  1774.             if (!no_color_flag)
  1775.             textcolor(bolt_color(typ));
  1776. #endif
  1777.             print('*', i, j);
  1778. #ifdef TC_COLOR
  1779.             if (!no_color_flag)
  1780.             textcolor(LIGHTGRAY);    /* prob don't need here, but... -CFT */
  1781. #endif
  1782.         }
  1783.     put_qio();
  1784. #ifdef MSDOS
  1785.     delay(25 * delay_spd);       /* milliseconds */
  1786. #else
  1787.     usleep(25000 * delay_spd); /* useconds */
  1788. #endif
  1789.  
  1790. /* now erase the ball, since effects below may use msg_print, and pause
  1791.  * indefinitely, so we want ball gone before then -CFT 
  1792.  */
  1793.     for (i = y - max_dis; i <= y + max_dis; i++)
  1794.         for (j = x - max_dis; j <= x + max_dis; j++)
  1795.         if (in_bounds(i, j) && (distance(y, x, i, j) <= max_dis) &&
  1796.             los(y, x, i, j) && (cave[i][j].fval <= MAX_OPEN_SPACE) &&
  1797.             panel_contains(i, j))
  1798.             lite_spot(i, j);   /* draw what is below the '*' */
  1799.     put_qio();
  1800.     }
  1801.  
  1802. /* first, go over area of affect and destroy preexisting items. This change
  1803.  * means that any treasure dropped by killed monsters is safe from the effects
  1804.  * of this ball (but not from any later balls/breathes, even if they happen
  1805.  * before the player gets a chance to pick up that scroll of *Acquirement*). 
  1806.  * The assumption is made that this treasure was shielded from the effects by
  1807.  * the corpse of the killed monster. -CFT 
  1808.  */
  1809.     for (i = y - max_dis; i <= y + max_dis; i++)
  1810.     for (j = x - max_dis; j <= x + max_dis; j++)
  1811.         if (in_bounds(i, j) && (distance(y, x, i, j) <= max_dis)
  1812.         && los(y, x, i, j) && (cave[i][j].tptr != 0)
  1813.         && (*destroy) (&t_list[cave[i][j].tptr]))
  1814.         delete_object(i, j);
  1815.  
  1816. /* now go over area of affect and DO something to monsters */
  1817.     for (i = y - max_dis; i <= y + max_dis; i++)
  1818.     for (j = x - max_dis; j <= x + max_dis; j++)
  1819.         if (in_bounds(i, j) && (distance(y, x, i, j) <= max_dis)
  1820.         && los(y, x, i, j)) {
  1821.  
  1822.         c_ptr = &cave[i][j];
  1823.         if ((c_ptr->tptr != 0) && (*destroy) (&t_list[c_ptr->tptr]))
  1824.             (void)delete_object(i, j);
  1825.         if (c_ptr->fval <= MAX_OPEN_SPACE) {
  1826.             if ((c_ptr->cptr > 1) && (c_ptr->cptr != monptr)) {
  1827.             dam = dam_hp;
  1828.             m_ptr = &m_list[c_ptr->cptr];
  1829.             spell_hit_monster(m_ptr, typ, &dam, distance(i, j, y, x) + 1,
  1830.                       &ny, &nx, FALSE);
  1831.             c_ptr = &cave[ny][nx];    /* may be new location if teleported
  1832.                                                  * by gravity warp... */
  1833.             m_ptr = &m_list[c_ptr->cptr];    /* and even if not, may be new
  1834.                              * monster if chaos polymorphed */
  1835.             r_ptr = &c_list[m_ptr->mptr];
  1836.  
  1837.             /*
  1838.              * can not call mon_take_hit here, since player does not
  1839.              * get experience for kill 
  1840.              */
  1841.             if (dam < 1)
  1842.                 dam = 1;
  1843.             m_ptr->hp = m_ptr->hp - dam;
  1844.             m_ptr->csleep = 0;
  1845.  
  1846. /* prevent unique monster from death by other monsters.  It causes trouble (monster not
  1847.  * marked as dead, quest monsters don't satisfy quest, etc).  So, we let
  1848.  * them live, but extremely wimpy.  This isn't great, because monster might heal
  1849.  * itself before player's next swing... -CFT
  1850.  */
  1851.             if ((r_ptr->cdefense & UNIQUE) && (m_ptr->hp < 0))
  1852.                 m_ptr->hp = 0;
  1853.  
  1854.             if (m_ptr->hp < 0) {
  1855.                 object_level = (dun_level + r_ptr->level) >> 1;
  1856.                 coin_type = 0;
  1857.                 get_coin_type(r_ptr);
  1858.                 treas = monster_death((int)m_ptr->fy, (int)m_ptr->fx,
  1859.                           r_ptr->cmove, 0, 0);
  1860.                 coin_type = 0;
  1861.                 /* recall even invisible uniques -CWS */
  1862.                 if (m_ptr->ml || (c_list[m_ptr->mptr].cdefense & UNIQUE)) {
  1863.                 tmp = (c_recall[m_ptr->mptr].r_cmove & CM_TREASURE)
  1864.                     >> CM_TR_SHIFT;
  1865.                 if (tmp > ((treas & CM_TREASURE) >> CM_TR_SHIFT))
  1866.                     treas = (treas & ~CM_TREASURE) | (tmp << CM_TR_SHIFT);
  1867.                 c_recall[m_ptr->mptr].r_cmove = treas |
  1868.                     (c_recall[m_ptr->mptr].r_cmove & ~CM_TREASURE);
  1869.                 }
  1870.             /* It ate an already processed monster.  Handle normally. */
  1871.                 if (monptr < c_ptr->cptr)
  1872.                 delete_monster((int)c_ptr->cptr);
  1873.  
  1874. /* If it eats this monster, an already processed monster will take its place,
  1875.  * causing all kinds of havoc. Delay the kill a bit.
  1876.  */
  1877.                 else
  1878.                 fix1_delete_monster((int)c_ptr->cptr);
  1879.             }
  1880.             } else if (c_ptr->cptr == 1) {
  1881.             dam = (dam_hp / (distance(i, j, y, x) + 1));
  1882.             m_ptr = &m_list[monptr];
  1883.             /* let's do at least one point of damage */
  1884.             /* prevents randint(0) problem with poison_gas, also */
  1885.             if (dam <= 0)
  1886.                 dam = 1;
  1887.             if (dam > 1600)
  1888.                 dam = 1600;
  1889.             switch (typ) {
  1890.               case GF_LIGHTNING:
  1891.                 light_dam(dam, ddesc);
  1892.                 break;
  1893.               case GF_POISON_GAS:
  1894.                 poison_gas(dam, ddesc);
  1895.                 break;
  1896.               case GF_ACID:
  1897.                 acid_dam(dam, ddesc);
  1898.                 break;
  1899.               case GF_FROST:
  1900.                 cold_dam(dam, ddesc);
  1901.                 break;
  1902.               case GF_FIRE:
  1903.                 fire_dam(dam, ddesc);
  1904.                 break;
  1905.               case GF_MAGIC_MISSILE:
  1906.                 take_hit(dam, ddesc);
  1907.                 break;
  1908.               case GF_HOLY_ORB:
  1909.                 dam /= 2;    /* player should take less damage
  1910.                      * from "good" power-CFT */
  1911.                 take_hit(dam, ddesc);
  1912.                 break;
  1913.               case GF_ARROW:    /* maybe can miss? */
  1914.                 take_hit(dam, ddesc);
  1915.                 break;
  1916.               case GF_PLASMA:    /* no resist to plasma? */
  1917.                 take_hit(dam, ddesc);
  1918.                 if (!py.flags.sound_resist)
  1919.                 stun_player(randint(
  1920.                 (dam_hp > 40) ? 35 : (dam_hp * 3 / 4 + 5)));
  1921.                 break;
  1922.               case GF_NETHER:
  1923.                 if (py.flags.nether_resist) {
  1924.                 dam *= 6;    /* these 2 lines give avg dam
  1925.                          * of .655, ranging from */
  1926.                 dam /= (randint(5) + 6);    /* .858 to .5 -CFT */
  1927.                 } else {    /* no resist */
  1928.                 if (py.flags.hold_life && randint(3) > 1)
  1929.                     msg_print("You keep hold of your life force!");
  1930.                 else if (py.flags.hold_life) {
  1931.                     msg_print("You feel your life slipping away!");
  1932.                     lose_exp(200 + (py.misc.exp/1000) * MON_DRAIN_LIFE);
  1933.                 } else {
  1934.                     msg_print("You feel your life draining away!");
  1935.                     lose_exp(200 + (py.misc.exp/100) * MON_DRAIN_LIFE);
  1936.                 }
  1937.                 }
  1938.                 take_hit(dam, ddesc);
  1939.                 break;
  1940.               case GF_WATER:
  1941.                 if (!py.flags.sound_resist)
  1942.                 stun_player(randint(55));
  1943.                 if (!player_saves() && !py.flags.confusion_resist
  1944.                 && !py.flags.chaos_resist) {
  1945.                 if ((py.flags.confused > 0) &&
  1946.                     (py.flags.confused < 32000))
  1947.                     py.flags.confused += 6;
  1948.                 else
  1949.                     py.flags.confused = randint(8) + 6;
  1950.                 }
  1951.                 take_hit(dam, ddesc);
  1952.                 break;
  1953.               case GF_CHAOS:
  1954.                 if (py.flags.chaos_resist) {
  1955.                 dam *= 6;    /* these 2 lines give avg dam
  1956.                          * of .655, ranging from */
  1957.                 dam /= (randint(6) + 6);    /* .858 to .5 -CFT */
  1958.                 }
  1959.                 if ((!py.flags.confusion_resist) &&
  1960.                 (!py.flags.chaos_resist)) {
  1961.                 if (py.flags.confused > 0)
  1962.                     py.flags.confused += 12;
  1963.                 else
  1964.                     py.flags.confused = randint(20) + 10;
  1965.                 }
  1966.                 if (!py.flags.chaos_resist)
  1967.                 py.flags.image += randint(10);
  1968.                 if (!py.flags.nether_resist && !py.flags.chaos_resist) {
  1969.                 if (py.flags.hold_life && randint(3) > 1)
  1970.                     msg_print("You keep hold of your life force!");
  1971.                 else if (py.flags.hold_life) {
  1972.                     msg_print("You feel your life slipping away!");
  1973.                     lose_exp(500 + (py.misc.exp/1000) * MON_DRAIN_LIFE);
  1974.                 } else {
  1975.                     msg_print("You feel your life draining away!");
  1976.                     lose_exp(5000 + (py.misc.exp/100) * MON_DRAIN_LIFE);
  1977.                 }
  1978.                 }
  1979.                 take_hit(dam, ddesc);
  1980.                 break;
  1981.               case GF_SHARDS:
  1982.                 if (py.flags.shards_resist) {
  1983.                 dam *= 6;    /* these 2 lines give avg dam
  1984.                          * of .655, ranging from */
  1985.                 dam /= (randint(6) + 6);    /* .858 to .5 -CFT */
  1986.                 } else {
  1987.                 cut_player(dam);    /* ouch! */
  1988.                 }
  1989.                 take_hit(dam, ddesc);
  1990.                 break;
  1991.               case GF_SOUND:
  1992.                 if (py.flags.sound_resist) {
  1993.                 dam *= 5;
  1994.                 dam /= (randint(6) + 6);
  1995.                 } else {
  1996.                 stun_player(randint((dam > 90) ? 35 : (dam / 3 + 5)));
  1997.                 }
  1998.                 take_hit(dam, ddesc);
  1999.                 break;
  2000.               case GF_CONFUSION:
  2001.                 if (py.flags.confusion_resist) {
  2002.                 dam *= 5;    /* these 2 lines give avg dam
  2003.                          * of .655, ranging from */
  2004.                 dam /= (randint(6) + 6);    /* .858 to .5 -CFT */
  2005.                 }
  2006.                 if (!py.flags.confusion_resist && !py.flags.chaos_resist) {
  2007.                 if (py.flags.confused > 0)
  2008.                     py.flags.confused += 12;
  2009.                 else
  2010.                     py.flags.confused = randint(20) + 10;
  2011.                 }
  2012.                 take_hit(dam, ddesc);
  2013.                 break;
  2014.               case GF_DISENCHANT:
  2015.                 if (py.flags.disenchant_resist) {
  2016.                 dam *= 6;    /* these 2 lines give avg dam
  2017.                          * of .655, ranging from */
  2018.                 dam /= (randint(6) + 6);    /* .858 to .5 -CFT */
  2019.                 } else {
  2020.                 int8u               disenchant = FALSE;
  2021.                 int8u               chance;
  2022.                 int                 t = 0;
  2023.                 inven_type         *i_ptr;
  2024.  
  2025.                 switch (randint(7)) {
  2026.                   case 1:
  2027.                     t = INVEN_BODY;
  2028.                     break;
  2029.                   case 2:
  2030.                     t = INVEN_BODY;
  2031.                     break;
  2032.                   case 3:
  2033.                     t = INVEN_ARM;
  2034.                     break;
  2035.                   case 4:
  2036.                     t = INVEN_OUTER;
  2037.                     break;
  2038.                   case 5:
  2039.                     t = INVEN_HANDS;
  2040.                     break;
  2041.                   case 6:
  2042.                     t = INVEN_HEAD;
  2043.                     break;
  2044.                   case 7:
  2045.                     t = INVEN_FEET;
  2046.                     break;
  2047.                 }
  2048.                 i_ptr = &inventory[t];
  2049.                 chance = 1;
  2050.                 /* Artifacts have 2/3 chance to resist -DGK */
  2051.                 if (i_ptr->flags2 & TR_ARTIFACT)
  2052.                     chance = randint(3);
  2053.                 if ((i_ptr->tohit > 0) && (chance == 1)) {
  2054.                     i_ptr->tohit -= randint(2);
  2055.                 /* don't send it below zero */
  2056.                     if (i_ptr->tohit < 0)
  2057.                     i_ptr->tohit = 0;
  2058.                     disenchant = TRUE;
  2059.                 }
  2060.                 if ((i_ptr->todam > 0) && (chance == 1)) {
  2061.                     i_ptr->todam -= randint(2);
  2062.                 /* don't send it below zero */
  2063.                     if (i_ptr->todam < 0)
  2064.                     i_ptr->todam = 0;
  2065.                     disenchant = TRUE;
  2066.                 }
  2067.                 if ((i_ptr->toac > 0) && (chance == 1)) {
  2068.                     i_ptr->toac -= randint(2);
  2069.                 /* don't send it below zero */
  2070.                     if (i_ptr->toac < 0)
  2071.                     i_ptr->toac = 0;
  2072.                     disenchant = TRUE;
  2073.                 }
  2074.                 if (disenchant || (chance != 1)) {
  2075.                     vtype               t1, t2;
  2076.  
  2077.                     objdes(t1, &inventory[t], FALSE);
  2078.                     if (chance != 1)
  2079.                     sprintf(t2, "Your %s (%c) %s disenchanted!", t1,
  2080.                         i + 'a' - INVEN_WIELD,
  2081.                         (inventory[i].number != 1) ?
  2082.                         "were" : "was");
  2083.                     else
  2084.                     sprintf(t2, "Your %s (%c) %s disenchantment!",
  2085.                         t1,
  2086.                         i + 'a' - INVEN_WIELD,
  2087.                         (inventory[i].number != 1) ?
  2088.                         "resist" : "resists");
  2089.                     msg_print(t2);
  2090.                     calc_bonuses();
  2091.                 }
  2092.                 }
  2093.                 take_hit(dam, ddesc);
  2094.                 break;
  2095.               case GF_NEXUS:
  2096.                 /* no spec. effects from nexus bolt, only breath -CFT */
  2097.                 if (py.flags.nexus_resist) {
  2098.                 dam *= 6;    /* these 2 lines give avg dam
  2099.                          * of .655, ranging from */
  2100.                 dam /= (randint(6) + 6);    /* .858 to .5 -CFT */
  2101.                 } else {    /* special effects */
  2102.                 switch (randint(7)) {
  2103.                   case 1:
  2104.                   case 2:
  2105.                   case 3:
  2106.                     teleport(200);
  2107.                     break;
  2108.                   case 4:
  2109.                   case 5:
  2110.                     teleport_to((int)m_ptr->fy, (int)m_ptr->fx);
  2111.                     break;
  2112.                   case 6:
  2113.                     if (player_saves())
  2114.                     msg_print("You resist the effects.");
  2115.                     else {
  2116.                     int                 k = dun_level;
  2117.  
  2118.                     if (dun_level == Q_PLANE)
  2119.                         dun_level = 0;
  2120.                     else if (is_quest(dun_level))
  2121.                         dun_level -= 1;
  2122.                     else
  2123.                         dun_level += (-3) + 2 * randint(2);
  2124.                     if (dun_level < 0)
  2125.                         dun_level = 0;
  2126.                     if (k == Q_PLANE)
  2127.                 msg_print("You warp through a cross-dimension gate.");
  2128.                     else if (k < dun_level)
  2129.                         msg_print("You sink through the floor.");
  2130.                     else
  2131.                     msg_print("You rise up through the ceiling.");
  2132.                     new_level_flag = TRUE;
  2133.                     }
  2134.                     break;
  2135.                   case 7:
  2136.                     if (player_saves() && randint(2) == 1)
  2137.                     msg_print("You resist the effects.");
  2138.                     else {
  2139.                     int      max1, cur1, max2, cur2, ii, jj;
  2140.  
  2141.                     msg_print("Your body starts to scramble...");
  2142.                     ii = randint(6) - 1;
  2143.                     do {
  2144.                         jj = randint(6) - 1;
  2145.                     } while (ii == jj);
  2146.                     max1 = py.stats.max_stat[ii];
  2147.                     cur1 = py.stats.cur_stat[ii];
  2148.                     max2 = py.stats.max_stat[jj];
  2149.                     cur2 = py.stats.cur_stat[jj];
  2150.                     py.stats.max_stat[ii] = max2;
  2151.                     py.stats.cur_stat[ii] = cur2;
  2152.                     py.stats.max_stat[jj] = max1;
  2153.                     py.stats.cur_stat[jj] = cur1;
  2154.                     set_use_stat(ii);
  2155.                     set_use_stat(jj);
  2156.                     prt_stat(ii);
  2157.                     prt_stat(jj);
  2158.                     }
  2159.                 } /* switch for effects */
  2160.                 }
  2161.                 take_hit(dam, ddesc);
  2162.                 break;
  2163.               case GF_FORCE:
  2164.                 if (!py.flags.sound_resist)
  2165.                 stun_player(randint(20));
  2166.                 take_hit(dam, ddesc);
  2167.                 break;
  2168.               case GF_INERTIA:
  2169.                 if ((py.flags.slow > 0) && (py.flags.slow < 32000))
  2170.                 py.flags.slow += randint(5);
  2171.                 else {
  2172.                 msg_print("You feel less able to move.");
  2173.                 py.flags.slow = randint(5) + 3;
  2174.                 }
  2175.                 take_hit(dam, ddesc);
  2176.                 break;
  2177.               case GF_LIGHT:
  2178.                 if (py.flags.light_resist) {
  2179.                 dam *= 4;
  2180.                 dam /= (randint(6) + 6);
  2181.                 } else if (!blind && !py.flags.blindness_resist) {
  2182.                 msg_print("You are blinded by the flash!");
  2183.                 py.flags.blind += randint(6) + 3;
  2184.                 }
  2185.                 light_area(char_row, char_col, 0, max_dis);
  2186.                 take_hit(dam, ddesc);
  2187.                 break;
  2188.               case GF_DARK:
  2189.                 if (py.flags.dark_resist) {
  2190.                 dam *= 4;
  2191.                 dam /= (randint(6) + 6);
  2192.                 } else {
  2193.                 if (!blind) 
  2194.                     msg_print("The darkness prevents you from seeing!");
  2195.                 py.flags.blind += randint(5) + 2;
  2196.                 }
  2197.                 unlight_area(char_row, char_col);
  2198.                 take_hit(dam, ddesc);
  2199.                 break;
  2200.               case GF_TIME:    /* only some effects from
  2201.                          * time bolt -CFT */
  2202.                 switch (randint(10)) {
  2203.                   case 1:
  2204.                   case 2:
  2205.                   case 3:
  2206.                   case 4:
  2207.                   case 5:
  2208.                 msg_print("You feel life has clocked back.");
  2209.                 lose_exp(m_ptr->hp + (py.misc.exp / 300) * MON_DRAIN_LIFE);
  2210.                 break;
  2211.                   case 6:
  2212.                   case 7:
  2213.                   case 8:
  2214.                   case 9:
  2215.                 {
  2216.                     int                 t = 0;
  2217.  
  2218.                     switch (randint(6)) {
  2219.                       case 1:
  2220.                     t = A_STR;
  2221.                 msg_print("You're not as strong as you used to be...");
  2222.                     break;
  2223.                       case 2:
  2224.                     t = A_INT;
  2225.                 msg_print("You're not as bright as you used to be...");
  2226.                     break;
  2227.                       case 3:
  2228.                     t = A_WIS;
  2229.                 msg_print("You're not as wise as you used to be...");
  2230.                     break;
  2231.                       case 4:
  2232.                     t = A_DEX;
  2233.                 msg_print("You're not as agile as you used to be...");
  2234.                     break;
  2235.                       case 5:
  2236.                     t = A_CON;
  2237.                 msg_print("You're not as hale as you used to be...");
  2238.                     break;
  2239.                       case 6:
  2240.                     t = A_CHR;
  2241.             msg_print("You're not as beautiful as you used to be...");
  2242.                     break;
  2243.                     }
  2244.                 py.stats.cur_stat[t] = (py.stats.cur_stat[t] * 3) / 4;
  2245.                     if (py.stats.cur_stat[t] < 3)
  2246.                     py.stats.cur_stat[t] = 3;
  2247.                     set_use_stat(t);
  2248.                     prt_stat(t);
  2249.                 }
  2250.                 break;
  2251.                   case 10:
  2252.                 {
  2253.                     int                 ii;
  2254.  
  2255.                     for (ii = 0; ii < 6; ii++) {
  2256.                 py.stats.cur_stat[ii] = (py.stats.cur_stat[ii] * 3) / 4;
  2257.                     if (py.stats.cur_stat[ii] < 3)
  2258.                         py.stats.cur_stat[ii] = 3;
  2259.                     set_use_stat(ii);
  2260.                     prt_stat(ii);
  2261.                     }
  2262.                 }
  2263.                 msg_print("You're not as strong as you used to be...");
  2264.                 msg_print("You're not as bright as you used to be...");
  2265.                 msg_print("You're not as wise as you used to be...");
  2266.                 msg_print("You're not as agile as you used to be...");
  2267.                 msg_print("You're not as hale as you used to be...");
  2268.             msg_print("You're not as beautiful as you used to be...");
  2269.                 break;
  2270.                 } /* randint(10) for effects */
  2271.                 take_hit(dam, ddesc);
  2272.                 break;
  2273.               case GF_GRAVITY:
  2274.                 if ((!py.flags.sound_resist) && (!py.flags.ffall))    /* DGK */
  2275.                 stun_player(randint((dam > 90) ? 35 : (dam / 3 + 5)));
  2276.                 if (py.flags.ffall) {    /* DGK */
  2277.                 dam_hp *= 3;    /* these 2 lines give avg dam
  2278.                          * of .33, ranging from */
  2279.                 dam_hp /= (randint(6) + 6);    /* .427 to .25 -CFT */
  2280.                 } else {    /* DGK */
  2281.                 if ((py.flags.slow > 0) && (py.flags.slow < 32000))
  2282.                     py.flags.slow += randint(5);
  2283.                 else {
  2284.                     msg_print("You feel less able to move.");
  2285.                     py.flags.slow = randint(5) + 3;
  2286.                 }
  2287.                 } /* DGK */
  2288.                 msg_print("Gravity warps around you.");
  2289.                 teleport(5);
  2290.                 take_hit(dam, ddesc);
  2291.                 break;
  2292.               case GF_MANA:
  2293.                 take_hit(dam, ddesc);
  2294.                 break;
  2295.               case GF_METEOR:
  2296.                 take_hit(dam, ddesc);
  2297.                 break;
  2298.               case GF_ICE:
  2299.                 cold_dam(dam, ddesc);
  2300.                 if (!py.flags.sound_resist)
  2301.                 stun_player(randint(25));
  2302.                 if (!py.flags.shards_resist)
  2303.                 cut_player(damroll(8, 10));
  2304.                 break;
  2305.               default:
  2306.             msg_print("Unknown typ in breath().  This may mean trouble.");
  2307.             }
  2308.             }
  2309.         }
  2310.         }
  2311. /* show the ball of gas */
  2312.     put_qio();
  2313.  
  2314. /* erase ball and redraw */
  2315.     for (i = (y - max_dis); i <= (y + max_dis); i++)
  2316.     for (j = (x - max_dis); j <= (x + max_dis); j++)
  2317.         if (in_bounds(i, j) && panel_contains(i, j) &&
  2318.         (distance(y, x, i, j) <= max_dis))
  2319.         lite_spot(i, j);
  2320. }
  2321.  
  2322.  
  2323. int 
  2324. recharge(num)
  2325. register int num;
  2326. {
  2327.     int                 i, j, k, l, item_val;
  2328.     register int        res;
  2329.     register inven_type *i_ptr;
  2330.     int                 found = FALSE;
  2331.  
  2332.     res = FALSE;
  2333.     if (find_range(TV_STAFF, TV_WAND, &i, &j))
  2334.     found = TRUE;
  2335.     if (find_range(TV_ROD, TV_NEVER, &k, &l))
  2336.     found = TRUE;
  2337.  
  2338.     if (!found)
  2339.     msg_print("You have nothing to recharge.");
  2340.     else if (get_item(&item_val, "Recharge which item?",
  2341.               (k > -1) ? k : i, (j > -1) ? j : l, 0)) {
  2342.     i_ptr = &inventory[item_val];
  2343.     res = TRUE;
  2344.     if (i_ptr->tval == TV_ROD) {
  2345.         /* now allow players to speed up recharge time of rods -CFT */
  2346.         int16u              t_o = i_ptr->timeout, t;
  2347.  
  2348.         if (randint((100 - i_ptr->level + num) / 5) == 1) {    /* not today... */
  2349.         msg_print("The recharge backfires, and drains the rod further!");
  2350.         if (t_o < 32000)   /* don't overflow... */
  2351.             i_ptr->timeout = (t_o + 100) * 2;
  2352.         } else {
  2353.         t = (int16u) (num * damroll(2, 4));    /* rechange amount */
  2354.         if (t_o < t)
  2355.             i_ptr->timeout = 0;
  2356.         else
  2357.             i_ptr->timeout = t_o - t;
  2358.         }
  2359.     }
  2360.      /* if recharge rod... */ 
  2361.     else {               /* recharge wand/staff */
  2362.     /* recharge I = recharge(20) = 1/6 failure for empty 10th level wand   */
  2363.     /* recharge II = recharge(60) = 1/10 failure for empty 10th level wand */
  2364.     /* make it harder to recharge high level, and highly charged wands     */
  2365.  
  2366.         if (randint((num + 100 - (int)i_ptr->level - (10 * i_ptr->p1)) / 15) == 1) {
  2367.         msg_print("There is a bright flash of light.");
  2368.         inven_destroy(item_val);
  2369.         } else {
  2370.         num = (num / (i_ptr->level + 2)) + 1;
  2371.         i_ptr->p1 += 2 + randint(num);
  2372.         if (known2_p(i_ptr))
  2373.             clear_known2(i_ptr);
  2374.         clear_empty(i_ptr);
  2375.         }
  2376.     }
  2377.     }
  2378.     return (res);
  2379. }
  2380.  
  2381. /* Increase or decrease a creatures hit points        -RAK-     */
  2382. int 
  2383. hp_monster(dir, y, x, dam)
  2384. int dir, y, x, dam;
  2385. {
  2386.     register int        i;
  2387.     int                 flag, dist, monster;
  2388.     register cave_type *c_ptr;
  2389.     register monster_type *m_ptr;
  2390.     register creature_type *r_ptr;
  2391.     vtype               out_val, m_name;
  2392.  
  2393.     monster = FALSE;
  2394.     flag = FALSE;
  2395.     dist = 0;
  2396.     do {
  2397.     (void)mmove(dir, &y, &x);
  2398.     dist++;
  2399.     c_ptr = &cave[y][x];
  2400.     if ((dist > OBJ_BOLT_RANGE) || c_ptr->fval >= MIN_CLOSED_SPACE)
  2401.         flag = TRUE;
  2402.     else if (c_ptr->cptr > 1) {
  2403.         flag = TRUE;
  2404.         m_ptr = &m_list[c_ptr->cptr];
  2405.         r_ptr = &c_list[m_ptr->mptr];
  2406.         monster_name(m_name, m_ptr, r_ptr);
  2407.         monster = TRUE;
  2408.         i = mon_take_hit((int)c_ptr->cptr, dam, TRUE);
  2409.         if (i >= 0) {
  2410.         (void)sprintf(out_val, "%s dies in a fit of agony.", m_name);
  2411.         msg_print(out_val);
  2412.         prt_experience();
  2413.         } else if (dam > 0) {
  2414.         (void)sprintf(out_val,
  2415.                   pain_message((int)c_ptr->cptr, dam), m_name);
  2416.         msg_print(out_val);
  2417.         }
  2418.     }
  2419.     }
  2420.     while (!flag);
  2421.     return (monster);
  2422. }
  2423.  
  2424.  
  2425. /* Drains life; note it must be living.        -RAK-     */
  2426. int 
  2427. drain_life(dir, y, x, dam)
  2428. int dir, y, x, dam;
  2429. {
  2430.     register int            i;
  2431.     int                     flag, dist, drain;
  2432.     register cave_type     *c_ptr;
  2433.     register monster_type  *m_ptr;
  2434.     register creature_type *r_ptr;
  2435.     vtype                   out_val, m_name;
  2436.  
  2437.     drain = FALSE;
  2438.     flag = FALSE;
  2439.     dist = 0;
  2440.     do {
  2441.     (void)mmove(dir, &y, &x);
  2442.     dist++;
  2443.     c_ptr = &cave[y][x];
  2444.     if ((dist > OBJ_BOLT_RANGE) || c_ptr->fval >= MIN_CLOSED_SPACE)
  2445.         flag = TRUE;
  2446.     else if (c_ptr->cptr > 1) {
  2447.         flag = TRUE;
  2448.         m_ptr = &m_list[c_ptr->cptr];
  2449.         r_ptr = &c_list[m_ptr->mptr];
  2450.         if (((r_ptr->cdefense & UNDEAD) == 0) &&
  2451.         ((r_ptr->cdefense & DEMON) == 0) &&
  2452.         (r_ptr->cchar != 'E' && r_ptr->cchar != 'g' && r_ptr->cchar != 'v')) {
  2453.         drain = TRUE;
  2454.         monster_name(m_name, m_ptr, r_ptr);
  2455.         i = mon_take_hit((int)c_ptr->cptr, dam, TRUE);
  2456.         if (i >= 0) {
  2457.             (void)sprintf(out_val, "%s dies in a fit of agony.", m_name);
  2458.             msg_print(out_val);
  2459.             prt_experience();
  2460.         } else {
  2461.             (void)sprintf(out_val,
  2462.                    pain_message((int)c_ptr->cptr, dam), m_name);
  2463.             msg_print(out_val);
  2464.         }
  2465.         } else {
  2466.         if (r_ptr->cdefense & UNDEAD)
  2467.             c_recall[m_ptr->mptr].r_cdefense |= UNDEAD;
  2468.         else
  2469.             c_recall[m_ptr->mptr].r_cdefense |= DEMON;
  2470.         }
  2471.     }
  2472.     }
  2473.     while (!flag);
  2474.     return (drain);
  2475. }
  2476.  
  2477.  
  2478. /* Increase or decrease a creatures speed        -RAK-     */
  2479. /* NOTE: cannot slow a winning creature (BALROG)         */
  2480. int 
  2481. speed_monster(dir, y, x, spd)
  2482. int dir, y, x, spd;
  2483. {
  2484.     int                    flag, dist, speed;
  2485.     register cave_type     *c_ptr;
  2486.     register monster_type  *m_ptr;
  2487.     register creature_type *r_ptr;
  2488.     vtype                   out_val, m_name;
  2489.  
  2490.     speed = FALSE;
  2491.     flag = FALSE;
  2492.     dist = 0;
  2493.     do {
  2494.     (void)mmove(dir, &y, &x);
  2495.     dist++;
  2496.     c_ptr = &cave[y][x];
  2497.     if ((dist > OBJ_BOLT_RANGE) || c_ptr->fval >= MIN_CLOSED_SPACE)
  2498.         flag = TRUE;
  2499.     else if (c_ptr->cptr > 1) {
  2500.         flag = TRUE;
  2501.         m_ptr = &m_list[c_ptr->cptr];
  2502.         r_ptr = &c_list[m_ptr->mptr];
  2503.         monster_name(m_name, m_ptr, r_ptr);
  2504.         if (spd > 0) {
  2505.         m_ptr->cspeed += spd;
  2506.         m_ptr->csleep = 0;
  2507.         (void)sprintf(out_val, "%s starts moving faster.", m_name);
  2508.         msg_print(out_val);
  2509.         speed = TRUE;
  2510.         } else if ((r_ptr->level >
  2511.             randint((py.misc.lev - 10) < 1 ? 1 : (py.misc.lev - 10)) + 10) ||
  2512.                (r_ptr->cdefense & UNIQUE)) {
  2513.         (void)sprintf(out_val, "%s is unaffected.", m_name);
  2514.         msg_print(out_val);
  2515.         m_ptr->csleep = 0;
  2516.         } else {
  2517.         m_ptr->cspeed += spd;
  2518.         m_ptr->csleep = 0;
  2519.         (void)sprintf(out_val, "%s starts moving slower.", m_name);
  2520.         msg_print(out_val);
  2521.         speed = TRUE;
  2522.         }
  2523.     }
  2524.     }
  2525.     while (!flag);
  2526.     return (speed);
  2527. }
  2528.  
  2529.  
  2530. /* Confuse a creature                    -RAK-     */
  2531. int 
  2532. confuse_monster(dir, y, x, lvl)
  2533. int dir, y, x, lvl;
  2534. {
  2535.     int                     flag, dist, confuse;
  2536.     register cave_type     *c_ptr;
  2537.     register monster_type  *m_ptr;
  2538.     register creature_type *r_ptr;
  2539.     vtype                   out_val, m_name;
  2540.  
  2541.     confuse = FALSE;
  2542.     flag = FALSE;
  2543.     dist = 0;
  2544.     do {
  2545.     (void)mmove(dir, &y, &x);
  2546.     dist++;
  2547.     c_ptr = &cave[y][x];
  2548.     if ((dist > OBJ_BOLT_RANGE) || c_ptr->fval >= MIN_CLOSED_SPACE)
  2549.         flag = TRUE;
  2550.     else if (c_ptr->cptr > 1) {
  2551.         m_ptr = &m_list[c_ptr->cptr];
  2552.         r_ptr = &c_list[m_ptr->mptr];
  2553.         monster_name(m_name, m_ptr, r_ptr);
  2554.         flag = TRUE;
  2555.         if ((r_ptr->level >
  2556.         randint((py.misc.lev - 10) < 1 ? 1 : (py.misc.lev - 10)) + 10) ||
  2557.         (r_ptr->cdefense & UNIQUE ||
  2558.          r_ptr->spells2 & (BREATH_CO | BREATH_CH))) {
  2559.         if (m_ptr->ml && (r_ptr->cdefense & CHARM_SLEEP))
  2560.             c_recall[m_ptr->mptr].r_cdefense |= CHARM_SLEEP;
  2561.         (void)sprintf(out_val, "%s is unaffected.", m_name);
  2562.         msg_print(out_val);
  2563.         m_ptr->csleep = 0;
  2564.         } else {
  2565.         if (m_ptr->confused < 230)
  2566.             m_ptr->confused += (int8u) (damroll(3, (lvl / 2)) + 1);
  2567.         confuse = TRUE;
  2568.         m_ptr->csleep = 0;
  2569.         (void)sprintf(out_val, "%s appears confused.", m_name);
  2570.         msg_print(out_val);
  2571.         }
  2572.     }
  2573.     }
  2574.     while (!flag);
  2575.     return (confuse);
  2576. }
  2577.  
  2578.  
  2579. /* Scare a creature -DGK */
  2580. int 
  2581. fear_monster(dir, y, x, lvl)
  2582. int dir, y, x, lvl;
  2583. {
  2584.     int                     flag, dist, fear;
  2585.     register cave_type     *c_ptr;
  2586.     register monster_type  *m_ptr;
  2587.     register creature_type *r_ptr;
  2588.     vtype                   out_val, m_name;
  2589.  
  2590.     fear = FALSE;
  2591.     flag = FALSE;
  2592.     dist = 0;
  2593.     do {
  2594.     (void)mmove(dir, &y, &x);
  2595.     dist++;
  2596.     c_ptr = &cave[y][x];
  2597.     if ((dist > OBJ_BOLT_RANGE) || c_ptr->fval >= MIN_CLOSED_SPACE)
  2598.         flag = TRUE;
  2599.     else if (c_ptr->cptr > 1) {
  2600.         m_ptr = &m_list[c_ptr->cptr];
  2601.         r_ptr = &c_list[m_ptr->mptr];
  2602.         monster_name(m_name, m_ptr, r_ptr);
  2603.         flag = TRUE;
  2604.         if ((r_ptr->level >
  2605.         randint((py.misc.lev - 10) < 1 ? 1 : (py.misc.lev - 10)) + 10) ||
  2606.         (r_ptr->cdefense & UNIQUE)) {
  2607.         if (m_ptr->ml && (r_ptr->cdefense & CHARM_SLEEP))
  2608.             c_recall[m_ptr->mptr].r_cdefense |= CHARM_SLEEP;
  2609.         (void)sprintf(out_val, "%s is unaffected.", m_name);
  2610.         msg_print(out_val);
  2611.         m_ptr->csleep = 0;
  2612.         } else {
  2613.         if (m_ptr->monfear < 175)
  2614.             m_ptr->monfear += (int8u) (damroll(3, (lvl / 2)) + 1);
  2615.         fear = TRUE;
  2616.         m_ptr->csleep = 0;
  2617.         (void)sprintf(out_val, "%s flees in terror!", m_name);
  2618.         msg_print(out_val);
  2619.         }
  2620.     }
  2621.     }
  2622.     while (!flag);
  2623.     return (fear);
  2624. }
  2625.  
  2626. /* Sleep a creature.                    -RAK-     */
  2627. int 
  2628. sleep_monster(dir, y, x)
  2629. int dir, y, x;
  2630. {
  2631.     int                     flag, dist, sleep;
  2632.     register cave_type     *c_ptr;
  2633.     register monster_type  *m_ptr;
  2634.     register creature_type *r_ptr;
  2635.     vtype                   out_val, m_name;
  2636.  
  2637.     sleep = FALSE;
  2638.     flag = FALSE;
  2639.     dist = 0;
  2640.     do {
  2641.     (void)mmove(dir, &y, &x);
  2642.     dist++;
  2643.     c_ptr = &cave[y][x];
  2644.     if ((dist > OBJ_BOLT_RANGE) || c_ptr->fval >= MIN_CLOSED_SPACE)
  2645.         flag = TRUE;
  2646.     else if (c_ptr->cptr > 1) {
  2647.         m_ptr = &m_list[c_ptr->cptr];
  2648.         r_ptr = &c_list[m_ptr->mptr];
  2649.  
  2650.         flag = TRUE;
  2651.         monster_name(m_name, m_ptr, r_ptr);
  2652.         if ((r_ptr->level >
  2653.         randint((py.misc.lev - 10) < 1 ? 1 : (py.misc.lev - 10)) + 10) ||
  2654.         (r_ptr->cdefense & UNIQUE) || (r_ptr->cdefense & CHARM_SLEEP)) {
  2655.         if (m_ptr->ml && (r_ptr->cdefense & CHARM_SLEEP))
  2656.             c_recall[m_ptr->mptr].r_cdefense |= CHARM_SLEEP;
  2657.         (void)sprintf(out_val, "%s is unaffected.", m_name);
  2658.         msg_print(out_val);
  2659.         } else {
  2660.         m_ptr->csleep = 500;
  2661.         sleep = TRUE;
  2662.         (void)sprintf(out_val, "%s falls asleep.", m_name);
  2663.         msg_print(out_val);
  2664.         }
  2665.     }
  2666.     }
  2667.     while (!flag);
  2668.     return (sleep);
  2669. }
  2670.  
  2671.  
  2672. /* Turn stone to mud, delete wall.            -RAK-     */
  2673. int 
  2674. wall_to_mud(dir, y, x)
  2675. int dir, y, x;
  2676. {
  2677.     int                     i, wall, dist;
  2678.     bigvtype                out_val, tmp_str;
  2679.     register int            flag;
  2680.     register cave_type     *c_ptr;
  2681.     register monster_type  *m_ptr;
  2682.     register creature_type *r_ptr;
  2683.     vtype                   m_name;
  2684.  
  2685.     wall = FALSE;
  2686.     flag = FALSE;
  2687.     dist = 0;
  2688.     do {
  2689.     (void)mmove(dir, &y, &x);
  2690.     dist++;
  2691.     c_ptr = &cave[y][x];
  2692.     /* note, this ray can move through walls as it turns them to mud */
  2693.     if (dist == OBJ_BOLT_RANGE)
  2694.         flag = TRUE;
  2695.     if (c_ptr->fval == BOUNDARY_WALL) {
  2696.         flag = TRUE;
  2697.         if (test_light(y, x))
  2698.         msg_print("The wall resists your spell.");
  2699.     } else if ((c_ptr->fval >= MIN_CAVE_WALL)) {
  2700.         flag = TRUE;
  2701.         (void)twall(y, x, 1, 0);
  2702.         if (test_light(y, x)) {
  2703.         msg_print("The wall turns into mud.");
  2704.         check_view();
  2705.         wall = TRUE;
  2706.         }
  2707.     } else if ((c_ptr->tptr != 0) && (c_ptr->fval >= MIN_CLOSED_SPACE)) {
  2708.         flag = TRUE;
  2709.         if (panel_contains(y, x) && test_light(y, x)) {        
  2710.         objdes(tmp_str, &t_list[c_ptr->tptr], FALSE);
  2711.         if ((t_list[c_ptr->tptr].tval == TV_RUBBLE) && (randint(10)==1)) {
  2712.             delete_object(y,x);
  2713.             place_object(y,x);
  2714.             lite_spot(y,x);
  2715.             (void) sprintf(out_val,
  2716.                    "The %s turns into mud, revealing an object!",\
  2717.                    tmp_str);
  2718.         }
  2719.         else {
  2720.             (void) delete_object(y, x);
  2721.             (void) sprintf(out_val, "The %s turns into mud.", tmp_str);
  2722.         }
  2723.         msg_print(out_val);
  2724.         wall = TRUE;
  2725.         }
  2726.     }
  2727.     
  2728.     if (c_ptr->cptr > 1) {
  2729.         m_ptr = &m_list[c_ptr->cptr];
  2730.         r_ptr = &c_list[m_ptr->mptr];
  2731.         if (HURT_ROCK & r_ptr->cdefense) {
  2732.         monster_name(m_name, m_ptr, r_ptr);
  2733.         flag = m_ptr->ml;
  2734.         i = mon_take_hit((int)c_ptr->cptr, (20 + randint(30)), TRUE);
  2735.         if (flag) {
  2736.             if (i >= 0) {
  2737.             c_recall[i].r_cdefense |= HURT_ROCK;
  2738.             (void)sprintf(out_val, "%s dissolves!", m_name);
  2739.             msg_print(out_val);
  2740.             prt_experience();    /* print msg before calling prt_exp */
  2741.             } else {
  2742.             c_recall[m_ptr->mptr].r_cdefense |= HURT_ROCK;
  2743.             (void)sprintf(out_val, "%s grunts in pain!", m_name);
  2744.             msg_print(out_val);
  2745.             }
  2746.         }
  2747.         flag = TRUE;
  2748.         }
  2749.     }
  2750.     }
  2751.     while (!flag);
  2752.     return (wall);
  2753. }
  2754.  
  2755.  
  2756. /* Destroy all traps and doors in a given direction    -RAK-     */
  2757. int 
  2758. td_destroy2(dir, y, x)
  2759. int dir, y, x;
  2760. {
  2761.     register int         destroy2, dist;
  2762.     register cave_type  *c_ptr;
  2763.     register inven_type *t_ptr;
  2764.  
  2765.     destroy2 = FALSE;
  2766.     dist = 0;
  2767.     do {
  2768.     (void)mmove(dir, &y, &x);
  2769.     dist++;
  2770.     c_ptr = &cave[y][x];
  2771.     /* must move into first closed spot, as it might be a secret door */
  2772.     if (c_ptr->tptr != 0) {
  2773.         t_ptr = &t_list[c_ptr->tptr];
  2774.         if (t_ptr->tval == TV_CHEST) /* let's untrap it instead -CWS */
  2775.         t_ptr->flags &= ~(CH_TRAPPED | CH_LOCKED);
  2776.         else if ((t_ptr->tval == TV_INVIS_TRAP) || (t_ptr->tval == TV_VIS_TRAP) ||
  2777.              (t_ptr->tval == TV_OPEN_DOOR) || (t_ptr->tval == TV_CLOSED_DOOR)
  2778.              || (t_ptr->tval == TV_SECRET_DOOR)) {
  2779.         if (delete_object(y, x)) {
  2780.             msg_print("There is a bright flash of light!");
  2781.             destroy2 = TRUE;
  2782.         }
  2783.         }
  2784.     }
  2785.     }
  2786.     while ((dist <= OBJ_BOLT_RANGE) || c_ptr->fval <= MAX_OPEN_SPACE);
  2787.     return (destroy2);
  2788. }
  2789.  
  2790.  
  2791. /* polymorph is now uniform for poly/mass poly/choas poly, and only
  2792.    as deadly as chaos poly is.  This still makes polymorphing a bad
  2793.    idea, but it won't be automatically fatal. -CFT */
  2794. static int
  2795. poly(int mnum)
  2796. {
  2797.     register creature_type *c_ptr = &c_list[m_list[mnum].mptr];
  2798.     int y, x;
  2799.     int i,j,k;
  2800.     
  2801.     if (c_ptr->cdefense & UNIQUE) return 0;
  2802.     y = m_list[mnum].fy;
  2803.     x = m_list[mnum].fx;
  2804.     i = (randint(20)/randint(9))+1;
  2805.     k = j = c_ptr->level;
  2806.     if ((j -=i)<0) j = 0;
  2807.     if ((k +=i)>MAX_MONS_LEVEL) k = MAX_MONS_LEVEL;
  2808.     delete_monster(mnum);
  2809.     do {
  2810.     i = randint(m_level[k]-m_level[j])-1+m_level[j];  /* new creature index */
  2811.     } while (c_list[i].cdefense & UNIQUE);
  2812.     place_monster(y,x,i,FALSE);
  2813.     return 1;
  2814. }
  2815.  
  2816. /* polymorph now safer.  not safe, just safer -CFT */
  2817. /* Polymorph a monster                                  -RAK-   */
  2818. /* NOTE: cannot polymorph a winning creature (BALROG)            */
  2819. int
  2820. poly_monster(dir, y, x)
  2821. int dir, y, x;
  2822. {
  2823.     int                     dist, flag, flag2, p;
  2824.     register cave_type     *c_ptr;
  2825.     register creature_type *r_ptr;
  2826.     register monster_type  *m_ptr;
  2827.     vtype                   out_val, m_name;
  2828.     
  2829.     p = FALSE;
  2830.     flag = FALSE;
  2831.     flag2= FALSE;
  2832.     dist = 0;
  2833.     do {
  2834.     (void) mmove(dir, &y, &x);
  2835.     dist++;
  2836.     c_ptr = &cave[y][x];
  2837.     if ((dist > OBJ_BOLT_RANGE) || c_ptr->fval >= MIN_CLOSED_SPACE)
  2838.         flag = TRUE;
  2839.     else if (c_ptr->cptr > 1) {
  2840.         m_ptr = &m_list[c_ptr->cptr];
  2841.         r_ptr = &c_list[m_ptr->mptr];
  2842.         if ((r_ptr->level < randint((py.misc.lev-10)<1?1:(py.misc.lev-10))+10)
  2843.                 && !(r_ptr->cdefense & UNIQUE)) {
  2844.         poly(c_ptr->cptr);
  2845.         if (panel_contains(y, x) && (c_ptr->tl || c_ptr->pl))
  2846.             p = TRUE;
  2847.         } else {
  2848.         monster_name (m_name, m_ptr, r_ptr);
  2849.         (void) sprintf(out_val, "%s is unaffected.", m_name);
  2850.         msg_print(out_val);
  2851.         }
  2852.     }
  2853.     }
  2854.     while (!flag);
  2855.     return(p);
  2856. }
  2857.  
  2858.  
  2859. /* Create a wall.                    -RAK-     */
  2860. int 
  2861. build_wall(dir, y, x)
  2862. int dir, y, x;
  2863. {
  2864.     register int            i;
  2865.     int                     build, damage, dist, flag;
  2866.     register cave_type     *c_ptr;
  2867.     register monster_type  *m_ptr;
  2868.     register creature_type *r_ptr;
  2869.     vtype                   m_name, out_val;
  2870.  
  2871.     build = FALSE;
  2872.     dist = 0;
  2873.     flag = FALSE;
  2874.     do {
  2875.     (void)mmove(dir, &y, &x);
  2876.     dist++;
  2877.     c_ptr = &cave[y][x];
  2878.     if ((dist > OBJ_BOLT_RANGE) || c_ptr->fval >= MIN_CLOSED_SPACE)
  2879.         flag = TRUE;
  2880.     else {
  2881.         if (c_ptr->cptr > 1) {
  2882.         /* stop the wall building */
  2883.         flag = TRUE;
  2884.         m_ptr = &m_list[c_ptr->cptr];
  2885.         r_ptr = &c_list[m_ptr->mptr];
  2886.  
  2887.         if (!(r_ptr->cmove & CM_PHASE)) {
  2888.         /* monster does not move, can't escape the wall */
  2889.             if (r_ptr->cmove & CM_ATTACK_ONLY)
  2890.             damage = 250;
  2891.             else
  2892.             damage = damroll(4, 8);
  2893.  
  2894.             monster_name(m_name, m_ptr, r_ptr);
  2895.             (void)sprintf(out_val, "%s wails out in pain!", m_name);
  2896.             msg_print(out_val);
  2897.             i = mon_take_hit((int)c_ptr->cptr, damage, TRUE);
  2898.             if (i >= 0) {
  2899.             (void)sprintf(out_val, "%s is embedded in the rock.",
  2900.                       m_name);
  2901.             msg_print(out_val);
  2902.             /* prt_experience(); */
  2903.             }
  2904.         } else if (r_ptr->cchar == 'E' || r_ptr->cchar == 'X') {
  2905.         /*
  2906.          * must be an earth elemental or an earth spirit, or a Xorn
  2907.          * increase its hit points 
  2908.          */
  2909.             m_ptr->hp += damroll(4, 8);
  2910.         }
  2911.         }
  2912.         if (c_ptr->tptr != 0)
  2913.         if (((t_list[c_ptr->tptr].tval >= TV_MIN_WEAR) &&
  2914.              (t_list[c_ptr->tptr].tval <= TV_MAX_WEAR) &&
  2915.              (t_list[c_ptr->tptr].flags2 & TR_ARTIFACT))
  2916.             || (t_list[c_ptr->tptr].tval == TV_UP_STAIR)
  2917.             || (t_list[c_ptr->tptr].tval == TV_DOWN_STAIR)
  2918.             || (t_list[c_ptr->tptr].tval == TV_STORE_DOOR))
  2919.             continue;       /* don't bury the artifact/stair/store */
  2920.         else
  2921.             (void)delete_object(y, x);
  2922.         c_ptr->fval = MAGMA_WALL;
  2923.         c_ptr->fm = FALSE;
  2924.         lite_spot(y, x);
  2925.         i++;
  2926.         build = TRUE;
  2927.     }
  2928.     }
  2929.     while (!flag);
  2930.     return (build);
  2931. }
  2932.  
  2933.  
  2934. /* Replicate a creature                    -RAK-     */
  2935. int 
  2936. clone_monster(dir, y, x)
  2937. int dir, y, x;
  2938. {
  2939.     register cave_type *c_ptr;
  2940.     register int        dist, flag;
  2941.  
  2942.     dist = 0;
  2943.     flag = FALSE;
  2944.     do {
  2945.     (void)mmove(dir, &y, &x);
  2946.     dist++;
  2947.     c_ptr = &cave[y][x];
  2948.     if ((dist > OBJ_BOLT_RANGE) || c_ptr->fval >= MIN_CLOSED_SPACE)
  2949.         flag = TRUE;
  2950.     else if (c_ptr->cptr > 1) {
  2951.         m_list[c_ptr->cptr].csleep = 0;
  2952.     /* monptr of 0 is safe here, since can't reach here from creatures */
  2953.         return multiply_monster(y, x, (int)m_list[c_ptr->cptr].mptr, 0);
  2954.     }
  2955.     }
  2956.     while (!flag);
  2957.     return (FALSE);
  2958. }
  2959.  
  2960.  
  2961. /* Move the creature record to a new location        -RAK-     */
  2962. void 
  2963. teleport_away(monptr, dis)
  2964. int monptr, dis;
  2965. {
  2966.     register int           yn, xn, ctr;
  2967.     register monster_type *m_ptr;
  2968.  
  2969.     m_ptr = &m_list[monptr];
  2970.     ctr = 0;
  2971.     do {
  2972.     do {
  2973.         yn = m_ptr->fy + (randint(2 * dis + 1) - (dis + 1));
  2974.         xn = m_ptr->fx + (randint(2 * dis + 1) - (dis + 1));
  2975.     }
  2976.     while (!in_bounds(yn, xn));
  2977.     ctr++;
  2978.     if (ctr > 9) {
  2979.         ctr = 0;
  2980.         dis += 5;
  2981.     }
  2982.     }
  2983.     while ((cave[yn][xn].fval >= MIN_CLOSED_SPACE) || (cave[yn][xn].cptr != 0));
  2984.     move_rec((int)m_ptr->fy, (int)m_ptr->fx, yn, xn);
  2985.     lite_spot((int)m_ptr->fy, (int)m_ptr->fx);
  2986.     m_ptr->fy = yn;
  2987.     m_ptr->fx = xn;
  2988.  
  2989. /* this is necessary, because the creature is not currently visible in its
  2990.  * new position 
  2991.  */
  2992.     m_ptr->ml = FALSE;
  2993.     m_ptr->cdis = distance(char_row, char_col, yn, xn);
  2994.     update_mon(monptr);
  2995. }
  2996.  
  2997.  
  2998. /* Teleport player to spell casting creature        -RAK-     */
  2999. void 
  3000. teleport_to(ny, nx)
  3001. int ny, nx;
  3002. {
  3003.     int dis, ctr, y, x;
  3004.  
  3005.     dis = 1;
  3006.     ctr = 0;
  3007.     do {
  3008.     do {               /* bounds check added -CFT */
  3009.         y = ny + (randint(2 * dis + 1) - (dis + 1));
  3010.         x = nx + (randint(2 * dis + 1) - (dis + 1));
  3011.     } while (!in_bounds(y, x));
  3012.     ctr++;
  3013.     if (ctr > (4 * dis * dis + 4 * dis + 1)) {
  3014.         ctr = 0;
  3015.         dis++;
  3016.     }
  3017.     }
  3018.     while ((cave[y][x].fval >= MIN_CLOSED_SPACE) || (cave[y][x].cptr >= 2));
  3019.     move_rec(char_row, char_col, y, x);
  3020.  
  3021.     darken_player(char_row, char_col);
  3022.     char_row = y;
  3023.     char_col = x;
  3024.     check_view();
  3025. /* light creatures */
  3026.     creatures(FALSE);
  3027. }
  3028.  
  3029.  
  3030. /* Teleport all creatures in a given direction away    -RAK-     */
  3031. int 
  3032. teleport_monster(dir, y, x)
  3033. int dir, y, x;
  3034. {
  3035.     register int        flag, result, dist;
  3036.     register cave_type *c_ptr;
  3037.  
  3038.     flag = FALSE;
  3039.     result = FALSE;
  3040.     dist = 0;
  3041.     do {
  3042.     (void)mmove(dir, &y, &x);
  3043.     dist++;
  3044.     c_ptr = &cave[y][x];
  3045.     if ((dist > OBJ_BOLT_RANGE) || c_ptr->fval >= MIN_CLOSED_SPACE)
  3046.         flag = TRUE;
  3047.     else if (c_ptr->cptr > 1) {
  3048.         m_list[c_ptr->cptr].csleep = 0;    /* wake it up */
  3049.         teleport_away((int)c_ptr->cptr, MAX_SIGHT * 5);
  3050.         result = TRUE;
  3051.     }
  3052.     }
  3053.     while (!flag);
  3054.     return (result);
  3055. }
  3056.  
  3057.  
  3058. /* Delete all creatures within max_sight distance    -RAK-     */
  3059. /* NOTE : Winning creatures cannot be genocided             */
  3060. int 
  3061. mass_genocide(spell)
  3062. int spell;
  3063. {
  3064.     register int        i, result;
  3065.     register monster_type *m_ptr;
  3066.     register creature_type *r_ptr;
  3067.  
  3068.     result = FALSE;
  3069.     for (i = mfptr - 1; i >= MIN_MONIX; i--) {
  3070.     m_ptr = &m_list[i];
  3071.     r_ptr = &c_list[m_ptr->mptr];
  3072.     if (((m_ptr->cdis <= MAX_SIGHT) && ((r_ptr->cmove & CM_WIN) == 0) &&
  3073.          ((r_ptr->cdefense & UNIQUE) == 0)) || (wizard &&
  3074.                           (m_ptr->cdis <= MAX_SIGHT))) {
  3075.         delete_monster(i);
  3076.         if (spell) {
  3077.         take_hit(randint(3), "the strain of casting Mass Genocide");
  3078.         prt_chp();
  3079.         put_qio();
  3080. #ifdef MSDOS
  3081.         delay(20* delay_spd);    /* milliseconds */
  3082. #else
  3083.         usleep(20000 * delay_spd);    /* useconds */
  3084. #endif
  3085.         }
  3086.         result = TRUE;
  3087.     }
  3088.     }
  3089.     return (result);
  3090. }
  3091.  
  3092. /* Delete all creatures of a given type from level.    -RAK-     */
  3093. /* This does not keep creatures of type from appearing later.     */
  3094. /* NOTE : Winning creatures can not be genocided. */
  3095. int 
  3096. genocide(spell)
  3097. int spell;
  3098. {
  3099.     register int            i, killed;
  3100.     char                    typ;
  3101.     register monster_type  *m_ptr;
  3102.     register creature_type *r_ptr;
  3103.     vtype                   out_val;
  3104.  
  3105.     killed = FALSE;
  3106.     if (get_com("Which type of creature do you wish exterminated?", &typ))
  3107.     for (i = mfptr - 1; i >= MIN_MONIX; i--) {
  3108.         m_ptr = &m_list[i];
  3109.         r_ptr = &c_list[m_ptr->mptr];
  3110.         if ((unsigned) typ == c_list[m_ptr->mptr].cchar)
  3111.         if ((r_ptr->cmove & CM_WIN) == 0) {
  3112.             delete_monster(i);
  3113.             if (spell) {
  3114.             take_hit(randint(4), "the strain of casting Genocide");
  3115.             prt_chp();
  3116.             put_qio();
  3117. #ifdef MSDOS
  3118.             delay(20 * delay_spd);    /* milliseconds */
  3119. #else
  3120.             usleep(20000 * delay_spd);    /* useconds */
  3121. #endif
  3122.             }
  3123.             killed = TRUE;
  3124.         } else {
  3125.  
  3126.         /* genocide is a powerful spell, so we will let the player
  3127.          * know the names of the creatures he did not destroy, this
  3128.          * message makes no sense otherwise 
  3129.          */
  3130.             if (r_ptr->cdefense & UNIQUE)
  3131.             (void)sprintf(out_val, "%s is unaffected.", r_ptr->name);
  3132.             else
  3133.             (void)sprintf(out_val, "The %s is unaffected.", r_ptr->name);
  3134.             msg_print(out_val);
  3135.         }
  3136.     }
  3137.     return (killed);
  3138. }
  3139.  
  3140.  
  3141. /* Change speed of any creature .            -RAK-     */
  3142. /* NOTE: cannot slow a winning creature (BALROG)         */
  3143. int 
  3144. speed_monsters(spd)
  3145. int spd;
  3146. {
  3147.     register int        i, speed;
  3148.     register monster_type *m_ptr;
  3149.     register creature_type *r_ptr;
  3150.     vtype               out_val, m_name;
  3151.  
  3152.     speed = FALSE;
  3153.     for (i = mfptr - 1; i >= MIN_MONIX; i--) {
  3154.     m_ptr = &m_list[i];
  3155.     r_ptr = &c_list[m_ptr->mptr];
  3156.     monster_name(m_name, m_ptr, r_ptr);
  3157.  
  3158.     if (!los(char_row, char_col, (int)m_ptr->fy, (int)m_ptr->fx))
  3159.     /* do nothing */
  3160.         ;
  3161.     else if (spd > 0) {
  3162.         m_ptr->cspeed += spd;
  3163.         m_ptr->csleep = 0;
  3164.         if (m_ptr->ml) {
  3165.         speed = TRUE;
  3166.         (void)sprintf(out_val, "%s starts moving faster.", m_name);
  3167.         msg_print(out_val);
  3168.         }
  3169.     } else if ((r_ptr->level <
  3170.         randint((py.misc.lev - 10) < 1 ? 1 : (py.misc.lev - 10)) + 10) &&
  3171.            !(r_ptr->cdefense & UNIQUE)) {
  3172.         m_ptr->cspeed += spd;
  3173.         m_ptr->csleep = 0;
  3174.         if (m_ptr->ml) {
  3175.         (void)sprintf(out_val, "%s starts moving slower.", m_name);
  3176.         msg_print(out_val);
  3177.         speed = TRUE;
  3178.         }
  3179.     } else if (m_ptr->ml) {
  3180.         (void)sprintf(out_val, "%s is unaffected.", m_name);
  3181.         msg_print(out_val);
  3182.     }
  3183.     }
  3184.     return (speed);
  3185. }
  3186.  
  3187.  
  3188. /* Sleep any creature .        -RAK-     */
  3189. int 
  3190. sleep_monsters2()
  3191. {
  3192.     register int        i, sleep;
  3193.     register monster_type *m_ptr;
  3194.     register creature_type *r_ptr;
  3195.     vtype               out_val, m_name;
  3196.  
  3197.     sleep = FALSE;
  3198.     for (i = mfptr - 1; i >= MIN_MONIX; i--) {
  3199.     m_ptr = &m_list[i];
  3200.     r_ptr = &c_list[m_ptr->mptr];
  3201.     monster_name(m_name, m_ptr, r_ptr);
  3202.     if ((m_ptr->cdis > MAX_SIGHT) ||
  3203.         !los(char_row, char_col, (int)m_ptr->fy, (int)m_ptr->fx))
  3204.     /* do nothing */
  3205.         ;
  3206.     else if ((r_ptr->level >
  3207.         randint((py.misc.lev - 10) < 1 ? 1 : (py.misc.lev - 10)) + 10) ||
  3208.         (r_ptr->cdefense & UNIQUE) || (r_ptr->cdefense & CHARM_SLEEP)) {
  3209.         if (m_ptr->ml) {
  3210.         if (r_ptr->cdefense & CHARM_SLEEP)
  3211.             c_recall[m_ptr->mptr].r_cdefense |= CHARM_SLEEP;
  3212.         (void)sprintf(out_val, "%s is unaffected.", m_name);
  3213.         msg_print(out_val);
  3214.         }
  3215.     } else {
  3216.         m_ptr->csleep = 500;
  3217.         if (m_ptr->ml) {
  3218.         (void)sprintf(out_val, "%s falls asleep.", m_name);
  3219.         msg_print(out_val);
  3220.         sleep = TRUE;
  3221.         }
  3222.     }
  3223.     }
  3224.     return (sleep);
  3225. }
  3226.  
  3227.  
  3228. /* Polymorph any creature that player can see.  -RAK-   */
  3229. /* NOTE: cannot polymorph a winning creature (BALROG)            */
  3230. int
  3231. mass_poly()
  3232. {
  3233.     register int i;
  3234.     int mass;
  3235.     register monster_type  *m_ptr;
  3236.     register creature_type *r_ptr;
  3237.     
  3238.     mass = FALSE;
  3239.     for (i = mfptr - 1; i >= MIN_MONIX; i--) {
  3240.     m_ptr = &m_list[i];
  3241.     if (m_ptr->cdis <= MAX_SIGHT) {
  3242.         r_ptr = &c_list[m_ptr->mptr];
  3243.         if (((r_ptr->cmove & CM_WIN) == 0) && !(r_ptr->cdefense & UNIQUE)) {
  3244.         mass = poly(i);
  3245.         }
  3246.     }
  3247.     }
  3248.     return(mass);
  3249. }
  3250.  
  3251.  
  3252. /* Display evil creatures on current panel        -RAK-     */
  3253. int 
  3254. detect_evil()
  3255. {
  3256.     register int        i, flag;
  3257.     register monster_type *m_ptr;
  3258.  
  3259.     flag = FALSE;
  3260.     for (i = mfptr - 1; i >= MIN_MONIX; i--) {
  3261.     m_ptr = &m_list[i];
  3262.     if (panel_contains((int)m_ptr->fy, (int)m_ptr->fx) &&
  3263.         (EVIL & c_list[m_ptr->mptr].cdefense)) {
  3264.         m_ptr->ml = TRUE;
  3265.     /* works correctly even if hallucinating */
  3266.         print((char)c_list[m_ptr->mptr].cchar, (int)m_ptr->fy,
  3267.           (int)m_ptr->fx);
  3268.         flag = TRUE;
  3269.     }
  3270.     }
  3271.     if (flag) {
  3272.     msg_print("You sense the presence of evil!");
  3273.     msg_print(NULL);
  3274.     /* must unlight every monster just lighted */
  3275.     creatures(FALSE);
  3276.     }
  3277.     return (flag);
  3278. }
  3279.  
  3280.  
  3281. /* Change players hit points in some manner        -RAK-     */
  3282. int 
  3283. hp_player(num)
  3284. int num;
  3285. {
  3286.     register int          res;
  3287.     register struct misc *m_ptr;
  3288.  
  3289.     res = FALSE;
  3290.     m_ptr = &py.misc;
  3291.     if (m_ptr->chp < m_ptr->mhp) {
  3292.     m_ptr->chp += num;
  3293.     if (m_ptr->chp > m_ptr->mhp) {
  3294.         m_ptr->chp = m_ptr->mhp;
  3295.         m_ptr->chp_frac = 0;
  3296.     }
  3297.     prt_chp();
  3298.  
  3299.     num = num / 5;
  3300.     if (num < 3) {
  3301.         if (num == 0)
  3302.         msg_print("You feel a little better.");
  3303.         else
  3304.         msg_print("You feel better.");
  3305.     } else {
  3306.         if (num < 7)
  3307.         msg_print("You feel much better.");
  3308.         else
  3309.         msg_print("You feel very good.");
  3310.     }
  3311.     res = TRUE;
  3312.     }
  3313.     return (res);
  3314. }
  3315.  
  3316.  
  3317. /* Cure players confusion                -RAK-     */
  3318. int 
  3319. cure_confusion()
  3320. {
  3321.     register int           cure;
  3322.     register struct flags *f_ptr;
  3323.  
  3324.     cure = FALSE;
  3325.     f_ptr = &py.flags;
  3326.     if (f_ptr->confused > 1) {
  3327.     f_ptr->confused = 1;
  3328.     cure = TRUE;
  3329.     }
  3330.     return (cure);
  3331. }
  3332.  
  3333.  
  3334. /* Cure players blindness                -RAK-     */
  3335. int 
  3336. cure_blindness()
  3337. {
  3338.     register int           cure;
  3339.     register struct flags *f_ptr;
  3340.  
  3341.     cure = FALSE;
  3342.     f_ptr = &py.flags;
  3343.     if (f_ptr->blind > 1) {
  3344.     f_ptr->blind = 1;
  3345.     cure = TRUE;
  3346.     }
  3347.     return (cure);
  3348. }
  3349.  
  3350.  
  3351. /* Cure poisoning                    -RAK-     */
  3352. int 
  3353. cure_poison()
  3354. {
  3355.     register int           cure;
  3356.     register struct flags *f_ptr;
  3357.  
  3358.     cure = FALSE;
  3359.     f_ptr = &py.flags;
  3360.     if (f_ptr->poisoned > 1) {
  3361.     f_ptr->poisoned = 1;
  3362.     cure = TRUE;
  3363.     }
  3364.     return (cure);
  3365. }
  3366.  
  3367.  
  3368. /* Cure the players fear                -RAK-     */
  3369. int 
  3370. remove_fear()
  3371. {
  3372.     register int           result;
  3373.     register struct flags *f_ptr;
  3374.  
  3375.     result = FALSE;
  3376.     f_ptr = &py.flags;
  3377.     if (f_ptr->afraid > 1) {
  3378.     f_ptr->afraid = 1;
  3379.     result = TRUE;
  3380.     }
  3381.     return (result);
  3382. }
  3383.  
  3384.  
  3385. /* This is a fun one.  In a given block, pick some walls and     */
  3386. /* turn them into open spots.  Pick some open spots and turn     */
  3387. /* them into walls.  An "Earthquake" effect.           -RAK-   */
  3388. void 
  3389. earthquake()
  3390. {
  3391.     register int        i, j;
  3392.     register cave_type *c_ptr;
  3393.     register monster_type *m_ptr;
  3394.     register creature_type *r_ptr;
  3395.     int                 kill, damage, tmp, y, x;
  3396.     vtype               out_val, m_name;
  3397.  
  3398.     for (i = char_row - 10; i <= char_row + 10; i++)
  3399.     for (j = char_col - 10; j <= char_col + 10; j++)
  3400.         if (((i != char_row) || (j != char_col)) &&
  3401.         in_bounds(i, j) && (distance(char_row, char_col, i, j)<=10) &&
  3402.         (randint(8) == 1)) {
  3403.         c_ptr = &cave[i][j];
  3404.         if (c_ptr->tptr != 0)
  3405.             if (((t_list[c_ptr->tptr].tval >= TV_MIN_WEAR) &&
  3406.              (t_list[c_ptr->tptr].tval <= TV_MAX_WEAR) &&
  3407.              (t_list[c_ptr->tptr].flags2 & TR_ARTIFACT))
  3408.             || (t_list[c_ptr->tptr].tval == TV_UP_STAIR)
  3409.             || (t_list[c_ptr->tptr].tval == TV_DOWN_STAIR)
  3410.             || (t_list[c_ptr->tptr].tval == TV_STORE_DOOR))
  3411.             continue;  /* don't touch artifacts or stairs or
  3412.                     * stores -CFT */
  3413.             else
  3414.             (void)delete_object(i, j);
  3415.         if (c_ptr->cptr > 1) {
  3416.             m_ptr = &m_list[c_ptr->cptr];
  3417.             r_ptr = &c_list[m_ptr->mptr];
  3418.  
  3419.             if (!(r_ptr->cmove & CM_PHASE) && !(r_ptr->cdefense & BREAK_WALL)) {
  3420.             if ((movement_rate(c_ptr->cptr) == 0) ||
  3421.                 (r_ptr->cmove & CM_ATTACK_ONLY))
  3422.             /* monster can not move to escape the wall */
  3423.                 kill = TRUE;
  3424.             else {
  3425.             /* only kill if there is nowhere for the monster to escape to */
  3426.                 kill = TRUE;
  3427.                 for (y = i - 1; y <= i + 1; y++)
  3428.                 for (x = j - 1; x <= j + 1; x++)
  3429.                     if (cave[y][x].fval >= MIN_CLOSED_SPACE)
  3430.                     kill = FALSE;
  3431.             }
  3432.             if (kill)
  3433.                 damage = 320;
  3434.             else
  3435.                 damage = damroll(3 + randint(3), 8+randint(5));
  3436.             monster_name(m_name, m_ptr, r_ptr);
  3437.             (void)sprintf(out_val, "%s wails out in pain!", m_name);
  3438.             msg_print(out_val);
  3439.             i = mon_take_hit((int)c_ptr->cptr, damage, TRUE);
  3440.             if (i >= 0) {
  3441.                 (void)sprintf(out_val, "%s is embedded in the rock.",
  3442.                       m_name);
  3443.                 msg_print(out_val);
  3444.             /* prt_experience(); */
  3445.             }
  3446.             }
  3447.         }
  3448.         if ((c_ptr->fval >= MIN_CAVE_WALL) && (c_ptr->fval != BOUNDARY_WALL)) {
  3449.             c_ptr->fval = CORR_FLOOR;
  3450.             c_ptr->pl = FALSE;
  3451.             c_ptr->fm = FALSE;
  3452.         } else if (c_ptr->fval <= MAX_CAVE_FLOOR) {
  3453.             tmp = randint(10);
  3454.             if (tmp < 6)
  3455.             c_ptr->fval = QUARTZ_WALL;
  3456.             else if (tmp < 9)
  3457.             c_ptr->fval = MAGMA_WALL;
  3458.             else
  3459.             c_ptr->fval = GRANITE_WALL;
  3460.  
  3461.             c_ptr->fm = FALSE;
  3462.         }
  3463.         lite_spot(i, j);
  3464.         }
  3465. }
  3466.  
  3467.  
  3468. /* Evil creatures don't like this.               -RAK-   */
  3469. int 
  3470. protect_evil()
  3471. {
  3472.     register int           res;
  3473.     register struct flags *f_ptr;
  3474.  
  3475.     f_ptr = &py.flags;
  3476.     if (f_ptr->protevil == 0)
  3477.     res = TRUE;
  3478.     else
  3479.     res = FALSE;
  3480.     f_ptr->protevil += randint(25) + 3 * py.misc.lev;
  3481.     return (res);
  3482. }
  3483.  
  3484.  
  3485. /* Create some high quality mush for the player.    -RAK-        */
  3486. /* Nope, let's just fill him up and save everybody time... -CWS */
  3487. void 
  3488. create_food()
  3489. {
  3490.      msg_print("You feel full!");
  3491.      msg_print(NULL);
  3492. #if defined(SATISFY_HUNGER)                /* new create food code -CWS */
  3493.      py.flags.food = PLAYER_FOOD_MAX;
  3494. #else
  3495.      /* add to food timer rather than create mush - cba */
  3496.      add_food(object_list[OBJ_MUSH].p1);
  3497. #endif
  3498.      py.flags.status &= ~(PY_WEAK | PY_HUNGRY);
  3499.      prt_hunger();
  3500. }
  3501.  
  3502. int 
  3503. banish_creature(cflag, dist)
  3504. int32u cflag;
  3505. int    dist;
  3506. {
  3507.     register int           i;
  3508.     int                    dispel;
  3509.     register monster_type *m_ptr;
  3510.  
  3511.     dispel = FALSE;
  3512.     for (i = mfptr - 1; i >= MIN_MONIX; i--) {
  3513.     m_ptr = &m_list[i];
  3514.     if ((cflag & c_list[m_ptr->mptr].cdefense) &&
  3515.         (m_ptr->cdis <= MAX_SIGHT) &&
  3516.         los(char_row, char_col, (int)m_ptr->fy, (int)m_ptr->fx)) {
  3517.         c_recall[m_ptr->mptr].r_cdefense |= cflag;
  3518.         (void)teleport_away(i, dist);
  3519.         dispel = TRUE;
  3520.     }
  3521.     }
  3522.     return (dispel);
  3523. }
  3524.  
  3525. int 
  3526. probing()
  3527. {
  3528.     register int            i;
  3529.     int                     probe;
  3530.     register monster_type  *m_ptr;
  3531.     register creature_type *r_ptr;
  3532.     register recall_type   *mp;
  3533.     vtype                   out_val, m_name;
  3534.  
  3535.     msg_print("Probing...");
  3536.     probe = FALSE;
  3537.     for (i = mfptr - 1; i >= MIN_MONIX; i--) {
  3538.     m_ptr = &m_list[i];
  3539.     r_ptr = &c_list[m_ptr->mptr];
  3540.     mp = &c_recall[m_ptr->mptr];
  3541.     if ((m_ptr->cdis <= MAX_SIGHT) &&
  3542.         los(char_row, char_col, (int)m_ptr->fy, (int)m_ptr->fx) && 
  3543.         (m_ptr->ml)) {
  3544.         if (r_ptr->cdefense & UNIQUE)
  3545.         sprintf(m_name, "%s", r_ptr->name);
  3546.         else
  3547.         sprintf(m_name, "The %s", r_ptr->name);
  3548.         sprintf(out_val, "%s has %d hit points.", m_name, m_ptr->hp);
  3549.         move_cursor_relative(m_ptr->fy, m_ptr->fx);
  3550.         msg_print(out_val);
  3551.  
  3552. /* let's make probing do good things to the monster memory -CWS */
  3553.         mp->r_cdefense = r_ptr->cdefense;
  3554.         mp->r_cmove = (r_ptr->cmove & ~CM_TREASURE);
  3555.         probe = TRUE;
  3556.     }
  3557.     }
  3558.     if (probe)
  3559.     msg_print("That's all.");
  3560.     else
  3561.     msg_print("You find nothing to probe.");
  3562.     move_cursor_relative(char_row, char_col);
  3563.     return (probe);
  3564. }
  3565.  
  3566. /* Attempts to destroy a type of creature.  Success depends on     */
  3567. /* the creatures level VS. the player's level         -RAK-     */
  3568. int 
  3569. dispel_creature(cflag, damage)
  3570. int cflag;
  3571. int damage;
  3572. {
  3573.     register int            i;
  3574.     int                     k, dispel;
  3575.     register monster_type  *m_ptr;
  3576.     register creature_type *r_ptr;
  3577.     vtype                   out_val, m_name;
  3578.  
  3579.     dispel = FALSE;
  3580.     for (i = mfptr - 1; i >= MIN_MONIX; i--) {
  3581.     m_ptr = &m_list[i];
  3582.     if ((cflag & c_list[m_ptr->mptr].cdefense) &&
  3583.         (m_ptr->cdis <= MAX_SIGHT) &&
  3584.         los(char_row, char_col, (int)m_ptr->fy, (int)m_ptr->fx)) {
  3585.         r_ptr = &c_list[m_ptr->mptr];
  3586.         c_recall[m_ptr->mptr].r_cdefense |= cflag;
  3587.         monster_name (m_name, m_ptr, r_ptr);
  3588.         k = mon_take_hit(i, randint(damage), FALSE);
  3589.         if (k >= 0)
  3590.         (void)sprintf(out_val, "%s dissolves!", m_name);
  3591.         else
  3592.         (void)sprintf(out_val, "%s shudders.", m_name);
  3593.         msg_print(out_val);
  3594.         dispel = TRUE;
  3595.         if (k >= 0)
  3596.         prt_experience();
  3597.     }
  3598.     }
  3599.     return (dispel);
  3600. }
  3601.  
  3602.  
  3603. /* Attempt to turn (confuse) undead creatures.    -RAK-     */
  3604. int 
  3605. turn_undead()
  3606. {
  3607.     register int            i, turn_und;
  3608.     register monster_type  *m_ptr;
  3609.     register creature_type *r_ptr;
  3610.     vtype                   out_val, m_name;
  3611.  
  3612.     turn_und = FALSE;
  3613.     for (i = mfptr - 1; i >= MIN_MONIX; i--) {
  3614.     m_ptr = &m_list[i];
  3615.     r_ptr = &c_list[m_ptr->mptr];
  3616.     if ((UNDEAD & r_ptr->cdefense)
  3617.         && (m_ptr->cdis <= MAX_SIGHT)
  3618.         && (los(char_row, char_col, (int)m_ptr->fy, (int)m_ptr->fx))) {
  3619.         monster_name(m_name, m_ptr, r_ptr);
  3620.         if (((py.misc.lev + 1) > r_ptr->level) ||
  3621.         (randint(5) == 1)) {
  3622.         if (m_ptr->ml) {
  3623.             (void)sprintf(out_val, "%s runs frantically!", m_name);
  3624.             msg_print(out_val);
  3625.             turn_und = TRUE;
  3626.             c_recall[m_ptr->mptr].r_cdefense |= UNDEAD;
  3627.         }
  3628.         m_ptr->monfear = randint(py.misc.lev) * 2;
  3629.         } else if (m_ptr->ml) {
  3630.         (void)sprintf(out_val, "%s is unaffected.", m_name);
  3631.         msg_print(out_val);
  3632.         }
  3633.     }
  3634.     }
  3635.     return (turn_und);
  3636. }
  3637.  
  3638.  
  3639. /* Leave a glyph of warding. Creatures will not pass over! -RAK- */
  3640. void 
  3641. warding_glyph()
  3642. {
  3643.     register int        i;
  3644.     register cave_type *c_ptr;
  3645.  
  3646.     c_ptr = &cave[char_row][char_col];
  3647.     if (c_ptr->tptr == 0) {
  3648.     i = popt();
  3649.     c_ptr->tptr = i;
  3650.     invcopy(&t_list[i], OBJ_SCARE_MON);
  3651.     }
  3652. }
  3653.  
  3654.  
  3655. /* Lose a strength point.                -RAK-     */
  3656. void 
  3657. lose_str()
  3658. {
  3659.     if (!py.flags.sustain_str) {
  3660.     (void)dec_stat(A_STR);
  3661.     msg_print("You feel very weak.");
  3662.     } else
  3663.     msg_print("You feel weak for a moment;  it passes.");
  3664. }
  3665.  
  3666.  
  3667. /* Lose an intelligence point.                -RAK-     */
  3668. void 
  3669. lose_int()
  3670. {
  3671.     if (!py.flags.sustain_int) {
  3672.     (void)dec_stat(A_INT);
  3673.     msg_print("You become very dizzy.");
  3674.     } else
  3675.     msg_print("You become dizzy for a moment;  it passes.");
  3676. }
  3677.  
  3678.  
  3679. /* Lose a wisdom point.                    -RAK-     */
  3680. void 
  3681. lose_wis()
  3682. {
  3683.     if (!py.flags.sustain_wis) {
  3684.     (void)dec_stat(A_WIS);
  3685.     msg_print("You feel very naive.");
  3686.     } else
  3687.     msg_print("You feel naive for a moment;  it passes.");
  3688. }
  3689.  
  3690.  
  3691. /* Lose a dexterity point.                -RAK-     */
  3692. void 
  3693. lose_dex()
  3694. {
  3695.     if (!py.flags.sustain_dex) {
  3696.     (void)dec_stat(A_DEX);
  3697.     msg_print("You feel very sore.");
  3698.     } else
  3699.     msg_print("You feel sore for a moment;  it passes.");
  3700. }
  3701.  
  3702.  
  3703. /* Lose a constitution point.                -RAK-     */
  3704. void 
  3705. lose_con()
  3706. {
  3707.     if (!py.flags.sustain_con) {
  3708.     (void)dec_stat(A_CON);
  3709.     msg_print("You feel very sick.");
  3710.     } else
  3711.     msg_print("You feel sick for a moment;  it passes.");
  3712. }
  3713.  
  3714.  
  3715. /* Lose a charisma point.                -RAK-     */
  3716. void 
  3717. lose_chr()
  3718. {
  3719.     if (!py.flags.sustain_chr) {
  3720.     (void)dec_stat(A_CHR);
  3721.     msg_print("Your skin starts to itch.");
  3722.     } else
  3723.     msg_print("Your skin starts to itch, but feels better now.");
  3724. }
  3725.  
  3726.  
  3727. /* Lose experience                    -RAK-     */
  3728. void 
  3729. lose_exp(amount)
  3730. int32 amount;
  3731. {
  3732.     register int          i;
  3733.     register struct misc *m_ptr;
  3734.     register class_type  *c_ptr;
  3735.  
  3736.     m_ptr = &py.misc;
  3737.     if (amount > m_ptr->exp)
  3738.     m_ptr->exp = 0;
  3739.     else
  3740.     m_ptr->exp -= amount;
  3741.     prt_experience();
  3742.  
  3743.     i = 0;
  3744.     while (((player_exp[i] * m_ptr->expfact / 100) <= m_ptr->exp)
  3745.        && (i < MAX_PLAYER_LEVEL))
  3746.     i++;
  3747. /* increment i once more, because level 1 exp is stored in player_exp[0] */
  3748.     i++;
  3749.     if (i > MAX_PLAYER_LEVEL)
  3750.     i = MAX_PLAYER_LEVEL;
  3751.     if (m_ptr->lev != i) {
  3752.     m_ptr->lev = i;
  3753.  
  3754.     calc_hitpoints();
  3755.     c_ptr = &class[m_ptr->pclass];
  3756.     if (c_ptr->spell == MAGE) {
  3757.         calc_spells(A_INT);
  3758.         calc_mana(A_INT);
  3759.     } else if (c_ptr->spell == PRIEST) {
  3760.         calc_spells(A_WIS);
  3761.         calc_mana(A_WIS);
  3762.     }
  3763.     prt_level();
  3764.     prt_title();
  3765.     }
  3766. }
  3767.  
  3768.  
  3769. /* Slow Poison                        -RAK-     */
  3770. int 
  3771. slow_poison()
  3772. {
  3773.     register int           slow;
  3774.     register struct flags *f_ptr;
  3775.  
  3776.     slow = FALSE;
  3777.     f_ptr = &py.flags;
  3778.     if (f_ptr->poisoned > 0) {
  3779.     f_ptr->poisoned = f_ptr->poisoned / 2;
  3780.     if (f_ptr->poisoned < 1)
  3781.         f_ptr->poisoned = 1;
  3782.     slow = TRUE;
  3783.     msg_print("The effect of the poison has been reduced.");
  3784.     }
  3785.     return (slow);
  3786. }
  3787.  
  3788.  
  3789. /* Bless                        -RAK-     */
  3790. void 
  3791. bless(amount)
  3792. int amount;
  3793. {
  3794.     py.flags.blessed += amount;
  3795. }
  3796.  
  3797.  
  3798. /* Detect Invisible for period of time            -RAK-     */
  3799. void 
  3800. detect_inv2(amount)
  3801. int amount;
  3802. {
  3803.     py.flags.detect_inv += amount;
  3804. }
  3805.  
  3806.  
  3807. static void 
  3808. replace_spot(y, x, typ)
  3809. int y, x, typ;
  3810. {
  3811.     register cave_type *c_ptr;
  3812.  
  3813.     c_ptr = &cave[y][x];
  3814.     switch (typ) {
  3815.       case 1:
  3816.       case 2:
  3817.       case 3:
  3818.     c_ptr->fval = CORR_FLOOR;
  3819.     break;
  3820.       case 4:
  3821.       case 7:
  3822.       case 10:
  3823.     c_ptr->fval = GRANITE_WALL;
  3824.     break;
  3825.       case 5:
  3826.       case 8:
  3827.       case 11:
  3828.     c_ptr->fval = MAGMA_WALL;
  3829.     break;
  3830.       case 6:
  3831.       case 9:
  3832.       case 12:
  3833.     c_ptr->fval = QUARTZ_WALL;
  3834.     break;
  3835.     }
  3836.     c_ptr->pl = FALSE;
  3837.     c_ptr->fm = FALSE;
  3838.     c_ptr->lr = FALSE;           /* this is no longer part of a room */
  3839.     if (c_ptr->tptr != 0)
  3840.     (void)delete_object(y, x);
  3841.     if (c_ptr->cptr > 1)
  3842.     delete_monster((int)c_ptr->cptr);
  3843. }
  3844.  
  3845.  
  3846. /* The spell of destruction.                -RAK-     */
  3847. /* NOTE : Winning creatures that are deleted will be considered     */
  3848. /* as teleporting to another level.  This will NOT win the */
  3849. /* game.                               */
  3850. void 
  3851. destroy_area(y, x)
  3852. register int y, x;
  3853. {
  3854.     register int i, j, k;
  3855.  
  3856.     msg_print("There is a searing blast of light!");
  3857.     if (!py.flags.blindness_resist && !py.flags.light_resist)
  3858.     py.flags.blind += 10 + randint(10);
  3859.     if (dun_level > 0) {
  3860.     for (i = (y - 15); i <= (y + 15); i++)
  3861.         for (j = (x - 15); j <= (x + 15); j++)
  3862.         if (in_bounds(i, j) && (cave[i][j].fval != BOUNDARY_WALL) &&
  3863.             ((cave[i][j].tptr == 0) ||
  3864.              ((t_list[cave[i][j].tptr].tval != TV_UP_STAIR) &&
  3865.               (t_list[cave[i][j].tptr].tval != TV_DOWN_STAIR) &&
  3866.               (!(t_list[cave[i][j].tptr].flags2 & TR_ARTIFACT))))) {    /* DGK */
  3867.             k = distance(i, j, y, x);
  3868.             if (k == 0)       /* player's spot... */
  3869.             replace_spot(i, j, 1);    /* clear player's spot...
  3870.                          * from um55 -CFT */
  3871.             else if (k < 13)
  3872.             replace_spot(i, j, randint(6));
  3873.             else if (k < 16)
  3874.             replace_spot(i, j, randint(9));
  3875.         }
  3876.     }
  3877.  
  3878.     /* We need to redraw the screen. -DGK */
  3879.     if (py.flags.blindness_resist || py.flags.light_resist) {
  3880.     draw_cave();
  3881.     creatures(FALSE);       /* draw monsters */
  3882.     }
  3883. }
  3884.  
  3885. /* Revamped!  Now takes item pointer, number of times to try enchanting,
  3886.  * and a flag of what to try enchanting.  Artifacts resist enchantment
  3887.  * some of the time, and successful enchantment to at least +0 might
  3888.  * break a curse on the item.  -CFT */
  3889. /* Enchants a plus onto an item.                        -RAK-   */
  3890. int
  3891. enchant(inven_type *i_ptr, int n, int8u eflag)
  3892. {
  3893.     register int chance, res = FALSE, i, a = i_ptr->flags2 & TR_ARTIFACT;
  3894.     int table[13] = {  10,  50, 100, 200, 300, 400,
  3895.                            500, 700, 950, 990, 992, 995, 997 };
  3896.     for(i=0; i<n; i++){
  3897.     chance = 0;
  3898.     if (eflag & ENCH_TOHIT) {
  3899.         if (i_ptr->tohit < 1) chance = 0;
  3900.         else if (i_ptr->tohit > 13) chance = 1000;
  3901.         else chance = table[i_ptr->tohit-1];
  3902.         if ((randint(1000)>chance) && (!a || randint(7)>3)) {
  3903.         i_ptr->tohit++;
  3904.         res = TRUE;
  3905.         if ((i_ptr->tohit >= 0) && (randint(4)==1) && /* only when you get */
  3906.             (i_ptr->flags & TR_CURSED)) { /*  it above -1 -CFT */
  3907.             msg_print("The curse is broken! ");
  3908.             i_ptr->flags &= ~TR_CURSED;
  3909.             i_ptr->ident &= ~ID_DAMD;
  3910.         }
  3911.         }
  3912.     }
  3913.     if (eflag & ENCH_TODAM) {
  3914.         if (i_ptr->todam < 1) chance = 0;
  3915.         else if (i_ptr->todam > 13) chance = 1000;
  3916.         else chance = table[i_ptr->todam-1];
  3917.         if ((randint(1000)>chance) && (!a || randint(7)>3)) {
  3918.         i_ptr->todam++;
  3919.         res = TRUE;
  3920.         if ((i_ptr->todam >= 0) && (randint(4)==1) && /* only when you get */
  3921.             (i_ptr->flags & TR_CURSED)) { /*  it above -1 -CFT */
  3922.             msg_print("The curse is broken! ");
  3923.             i_ptr->flags &= ~TR_CURSED;
  3924.             i_ptr->ident &= ~ID_DAMD;
  3925.         }
  3926.         }
  3927.     }
  3928.     if (eflag & ENCH_TOAC) {
  3929.         if (i_ptr->toac < 1) chance = 0;
  3930.         else if (i_ptr->toac > 13) chance = 1000;
  3931.         else chance = table[i_ptr->toac-1];
  3932.         if ((randint(1000)>chance) && (!a || randint(7)>3)) {
  3933.         i_ptr->toac++;
  3934.         res = TRUE;
  3935.         if ((i_ptr->toac >= 0) && (randint(4)==1) && /* only when you get */
  3936.             (i_ptr->flags & TR_CURSED)) { /*  it above -1 -CFT */
  3937.             msg_print("The curse is broken! ");
  3938.             i_ptr->flags &= ~TR_CURSED;
  3939.             i_ptr->ident &= ~ID_DAMD;
  3940.         }
  3941.         }
  3942.     }
  3943.     } /* for loop */
  3944.     if (res) calc_bonuses ();
  3945.     return(res);
  3946. }
  3947.  
  3948.  
  3949. const char *
  3950. pain_message(monptr, dam)
  3951. int monptr, dam;
  3952. {
  3953.     register monster_type *m_ptr;
  3954.     creature_type      *c_ptr;
  3955.     int                 percentage, oldhp, newhp;
  3956.  
  3957.     if (dam == 0)
  3958.     return "%s is unharmed.";  /* avoid potential div by 0 */
  3959.  
  3960.     m_ptr = &m_list[monptr];
  3961.     c_ptr = &c_list[m_ptr->mptr];
  3962. #ifdef MSDOS               /* more fix -CFT */
  3963.     newhp = (int32) (m_ptr->hp);
  3964.     oldhp = newhp + (int32) dam;
  3965. #else
  3966.     newhp = m_ptr->hp;
  3967.     oldhp = newhp + dam;
  3968. #endif
  3969.     percentage = (newhp * 100) / oldhp;
  3970.  
  3971.     if ((c_ptr->cchar == 'j') ||   /* Non-verbal creatures like molds */
  3972.     (c_ptr->cchar == 'Q') || (c_ptr->cchar == 'v') ||
  3973.      (c_ptr->cchar == 'm') || ((c_ptr->cchar == 'e') && stricmp(c_ptr->name,
  3974.                                  "Beholder"))) {
  3975.     if (percentage > 95)
  3976.         return "%s barely notices.";
  3977.     if (percentage > 75)
  3978.         return "%s flinches.";
  3979.     if (percentage > 50)
  3980.         return "%s squelches.";
  3981.     if (percentage > 35) {
  3982.         if (randint(4) == 1) /* thanks to dbd@panacea.phys.utk.edu -CWS */
  3983.         return "%s quivers in pain.";
  3984.         else
  3985.         return "%s imitates Bill Cosby in pain.";
  3986.     }
  3987.     if (percentage > 20)
  3988.         return "%s writhes about.";
  3989.     if (percentage > 10)
  3990.         return "%s writhes in agony.";
  3991.     return "%s jerks limply.";
  3992.     } else if (c_ptr->cchar == 'C' || c_ptr->cchar == 'Z') {
  3993.     if (percentage > 95)
  3994.         return "%s shrugs off the attack.";
  3995.     if (percentage > 75)
  3996.         return "%s snarls with pain.";
  3997.     if (percentage > 50)
  3998.         return "%s yelps in pain.";
  3999.     if (percentage > 35)
  4000.         return "%s howls in pain.";
  4001.     if (percentage > 20)
  4002.         return "%s howls in agony.";
  4003.     if (percentage > 10)
  4004.         return "%s writhes in agony.";
  4005.     return "%s yelps feebly.";
  4006.     } else if (c_ptr->cchar == 'K' || c_ptr->cchar == 'c' || c_ptr->cchar == 'a' ||
  4007.     c_ptr->cchar == 'U' || c_ptr->cchar == 'q' || c_ptr->cchar == 'R' ||
  4008.     c_ptr->cchar == 'X' || c_ptr->cchar == 'b' || c_ptr->cchar == 'F' ||
  4009.     c_ptr->cchar == 'J' || c_ptr->cchar == 'l' || c_ptr->cchar == 'r' ||
  4010.     c_ptr->cchar == 's' || c_ptr->cchar == 'S' || c_ptr->cchar == 't') {
  4011.     if (percentage > 95)
  4012.         return "%s ignores the attack.";
  4013.     if (percentage > 75)
  4014.         return "%s grunts with pain.";
  4015.     if (percentage > 50)
  4016.         return "%s squeals in pain.";
  4017.     if (percentage > 35)
  4018.         return "%s shrieks in pain.";
  4019.     if (percentage > 20)
  4020.         return "%s shrieks in agony.";
  4021.     if (percentage > 10)
  4022.         return "%s writhes in agony.";
  4023.     return "%s cries out feebly.";
  4024.     } else {
  4025.     if (percentage > 95)
  4026.         return "%s shrugs off the attack.";
  4027.     if (percentage > 75)
  4028.         return "%s grunts with pain.";
  4029.     if (percentage > 50)
  4030.         return "%s cries out in pain.";
  4031.     if (percentage > 35)
  4032.         return "%s screams in pain.";
  4033.     if (percentage > 20)
  4034.         return "%s screams in agony.";
  4035.     if (percentage > 10)
  4036.         return "%s writhes in agony.";
  4037.     return "%s cries out feebly.";
  4038.     }
  4039. }
  4040.  
  4041. /* Removes curses from items in inventory        -RAK-     */
  4042. int 
  4043. remove_curse()
  4044. {
  4045.     register int         i, result;
  4046.     register inven_type *i_ptr;
  4047.  
  4048.     result = FALSE;
  4049.     for (i = INVEN_WIELD; i <= INVEN_OUTER; i++) {
  4050.     i_ptr = &inventory[i];
  4051.     if ((TR_CURSED & i_ptr->flags) &&
  4052.         (i_ptr->name2 != SN_MORGUL) &&
  4053.         (i_ptr->name2 != SN_CALRIS) &&
  4054.         (i_ptr->name2 != SN_MORMEGIL)) {
  4055.         if (!(!stricmp(object_list[i_ptr->index].name, "Power") &&
  4056.           (i_ptr->tval == TV_RING))) {
  4057.         i_ptr->flags &= ~TR_CURSED;
  4058.         i_ptr->ident &= ~ID_DAMD;    /* DGK */
  4059.         i_ptr->inscrip[0] = '\0';
  4060.         calc_bonuses();
  4061.         result = TRUE;
  4062.         }
  4063.     }
  4064.     }
  4065.     return (result);
  4066. }
  4067.  
  4068. int 
  4069. remove_all_curse()
  4070. {
  4071.     register int         i, result;
  4072.     register inven_type *i_ptr;
  4073.  
  4074.     result = FALSE;
  4075.     for (i = INVEN_WIELD; i <= INVEN_OUTER; i++) {
  4076.     i_ptr = &inventory[i];
  4077.     if (TR_CURSED & i_ptr->flags) {
  4078.         if (!(!stricmp(object_list[i_ptr->index].name, "Power") &&
  4079.           (i_ptr->tval == TV_RING))) {
  4080.         i_ptr->flags &= ~TR_CURSED;
  4081.         i_ptr->ident &= ~ID_DAMD;    /* DGK */
  4082.         calc_bonuses();
  4083.         i_ptr->inscrip[0] = '\0';
  4084.         result = TRUE;
  4085.         } else {
  4086.         msg_print("The One Ring resists all attempts to remove it!");
  4087.         }
  4088.     }
  4089.     }
  4090.     return (result);
  4091. }
  4092.  
  4093.  
  4094. /* Restores any drained experience            -RAK-     */
  4095. int 
  4096. restore_level()
  4097. {
  4098.     register int          restore;
  4099.     register struct misc *m_ptr;
  4100.  
  4101.     restore = FALSE;
  4102.     m_ptr = &py.misc;
  4103.     if (m_ptr->max_exp > m_ptr->exp) {
  4104.     restore = TRUE;
  4105.     msg_print("You feel your life energies returning.");
  4106.     /* this while loop is not redundant, ptr_exp may reduce the exp level */
  4107.     while (m_ptr->exp < m_ptr->max_exp) {
  4108.         m_ptr->exp = m_ptr->max_exp;
  4109.         prt_experience();
  4110.     }
  4111.     }
  4112.     return (restore);
  4113. }
  4114.  
  4115.  
  4116. /* this fn only exists to avoid duplicating this code in the selfknowledge fn. -CFT */
  4117. static void 
  4118. pause_if_screen_full(i, j)
  4119. int *i;
  4120. int  j;
  4121. {
  4122.     int t;
  4123.  
  4124.     if (*i == 22) {           /* is screen full? */
  4125.     prt("-- more --", *i, j);
  4126.     inkey();
  4127.     for (t = 2; t < 23; t++)
  4128.         erase_line(t, j);       /* don't forget to erase extra */
  4129.     prt("Your Attributes: (continued)", 1, j + 5);
  4130.     *i = 2;
  4131.     }
  4132. }
  4133.  
  4134. /* self-knowledge... idea from nethack.  Useful for determining powers and
  4135.  * resistences of items.  It saves the screen, clears it, then starts listing
  4136.  * attributes, a screenful at a time.  (There are a LOT of attributes to
  4137.  * list.  It will probably take 2 or 3 screens for a powerful character whose
  4138.  * using several artifacts...) -CFT 
  4139.  */
  4140.  
  4141. void 
  4142. self_knowledge()
  4143. {
  4144.     int    i, j;
  4145.     int32u f = 0L, f2 = 0L;
  4146.  
  4147.     for (i = INVEN_WIELD; i <= INVEN_LIGHT; i++) {    /* get flags from items */
  4148.     if (inventory[i].tval != TV_NOTHING) {
  4149.         if (inventory[i].p1 < 0) /* don't adjust TR_STATS if p1 is negative -CWS */
  4150.         f |= (inventory[i].flags & ~(TR_STATS | TR_SEARCH | TR_STEALTH) );
  4151.         else
  4152.         f |= inventory[i].flags;
  4153.         f2 |= inventory[i].flags2;
  4154.     }
  4155.     }
  4156.  
  4157.     save_screen();
  4158.  
  4159. /* map starts at 13, but I want a couple of spaces.
  4160.  * This means must start by erasing map...
  4161.  */
  4162.     j = 15;
  4163.     for (i = 1; i < 23; i++)
  4164.     erase_line(i, j - 2);       /* erase a couple of spaces to left */
  4165.  
  4166.     i = 1;
  4167.     prt("Your Attributes:", i++, j + 5);
  4168.  
  4169.     if (py.flags.blind > 0)
  4170.     prt("You cannot see.", i++, j);
  4171.     if (py.flags.confused > 0)
  4172.     prt("You are confused.", i++, j);
  4173.     if (py.flags.afraid > 0)
  4174.     prt("You are terrified.", i++, j);
  4175.     if (py.flags.cut > 0)
  4176.     prt("You are bleeding.", i++, j);
  4177.     if (py.flags.stun > 0)
  4178.     prt("You are stunned and reeling.", i++, j);
  4179.     if (py.flags.poisoned > 0)
  4180.     prt("You are poisoned.", i++, j);
  4181.     if (py.flags.image > 0)
  4182.     prt("You are hallucinating.", i++, j);
  4183.     if (py.flags.aggravate)
  4184.     prt("You aggravate monsters.", i++, j);
  4185.     if (py.flags.teleport)
  4186.     prt("Your position is very uncertain.", i++, j);
  4187.  
  4188.     if (py.flags.blessed > 0)
  4189.     prt("You feel rightous.", i++, j);
  4190.     if (py.flags.hero > 0)
  4191.     prt("You feel heroic.", i++, j);
  4192.     if (py.flags.shero > 0)
  4193.     prt("You are in a battle rage.", i++, j);
  4194.     if (py.flags.protevil > 0)
  4195.     prt("You are protected from evil.", i++, j);
  4196.     if (py.flags.shield > 0)
  4197.     prt("You are protected by a mystic shield.", i++, j);
  4198.     if (py.flags.invuln > 0)
  4199.     prt("You are temporarily invulnerable.", i++, j);
  4200.     if (py.flags.confuse_monster)
  4201.     prt("Your hands are glowing dull red.", i++, j);
  4202.     if (py.flags.new_spells > 0)
  4203.     prt("You can learn some more spells.", i++, j);
  4204.     if (py.flags.word_recall > 0)
  4205.     prt("You will soon be recalled.", i++, j);
  4206.  
  4207.     if (f & TR_STEALTH)
  4208.     prt("You are magically stealthy.", i++, j);
  4209.     if (f & TR_SEARCH) {
  4210.     prt("You are magically perceptive.", i++, j);
  4211.     pause_if_screen_full(&i, j);
  4212.     }
  4213.     if ((py.flags.see_infra) || (py.flags.tim_infra)) {
  4214.     prt("Your eyes are sensitive to infrared light.", i++, j);
  4215.     pause_if_screen_full(&i, j);
  4216.     }
  4217.     if ((py.flags.see_inv) || (py.flags.detect_inv)) {
  4218.     prt("You can see invisible creatures.", i++, j);
  4219.     pause_if_screen_full(&i, j);
  4220.     }
  4221.     if (py.flags.ffall) {
  4222.     prt("You land gently.", i++, j);
  4223.     pause_if_screen_full(&i, j);
  4224.     }
  4225.     if (py.flags.free_act) {
  4226.     prt("You have free action.", i++, j);
  4227.     pause_if_screen_full(&i, j);
  4228.     }
  4229.     if (py.flags.regenerate) {
  4230.     prt("You regenerate quickly.", i++, j);
  4231.     pause_if_screen_full(&i, j);
  4232.     }
  4233.     if (py.flags.slow_digest) {
  4234.     prt("Your appetite is small.", i++, j);
  4235.     pause_if_screen_full(&i, j);
  4236.     }
  4237.     if (py.flags.telepathy) {
  4238.     prt("You have ESP.", i++, j);
  4239.     pause_if_screen_full(&i, j);
  4240.     }
  4241.     if (py.flags.hold_life) {
  4242.     prt("You have a firm hold on your life force.", i++, j);
  4243.     pause_if_screen_full(&i, j);
  4244.     }
  4245.     if (py.flags.light) {
  4246.     prt("You are carrying a permanent light.", i++, j);
  4247.     pause_if_screen_full(&i, j);
  4248.     }
  4249.     if (py.flags.fear_resist) {
  4250.     prt("You are completely fearless.", i++, j);
  4251.     pause_if_screen_full(&i, j);
  4252.     }
  4253.     if (py.flags.blindness_resist) {
  4254.     prt("Your eyes are resistant to blindness.", i++, j);
  4255.     pause_if_screen_full(&i, j);
  4256.     }
  4257.     if (py.flags.fire_im) {
  4258.     prt("You are completely immune to fire.", i++, j);
  4259.     pause_if_screen_full(&i, j);
  4260.     } else if ((py.flags.fire_resist) && (py.flags.resist_heat)) {
  4261.     prt("You resist fire exceptionally well.", i++, j);
  4262.     pause_if_screen_full(&i, j);
  4263.     } else if ((py.flags.fire_resist) || (py.flags.resist_heat)) {
  4264.     prt("You are resistant to fire.", i++, j);
  4265.     pause_if_screen_full(&i, j);
  4266.     }
  4267.     if (py.flags.cold_im) {
  4268.     prt("You are completely immune to cold.", i++, j);
  4269.     pause_if_screen_full(&i, j);
  4270.     } else if ((py.flags.cold_resist) && (py.flags.resist_cold)) {
  4271.     prt("You resist cold exceptionally well.", i++, j);
  4272.     pause_if_screen_full(&i, j);
  4273.     } else if ((py.flags.cold_resist) || (py.flags.resist_cold)) {
  4274.     prt("You are resistant to cold.", i++, j);
  4275.     pause_if_screen_full(&i, j);
  4276.     }
  4277.     if (py.flags.acid_im) {
  4278.     prt("You are completely immune to acid.", i++, j);
  4279.     pause_if_screen_full(&i, j);
  4280.     } else if ((py.flags.acid_resist) && (py.flags.resist_acid)) {
  4281.     prt("You resist acid exceptionally well.", i++, j);
  4282.     pause_if_screen_full(&i, j);
  4283.     } else if ((py.flags.acid_resist) || (py.flags.resist_acid)) {
  4284.     prt("You are resistant to acid.", i++, j);
  4285.     pause_if_screen_full(&i, j);
  4286.     }
  4287.     if (py.flags.poison_im) {
  4288.     prt("You are completely immune to poison.", i++, j);
  4289.     pause_if_screen_full(&i, j);
  4290.     } else if ((py.flags.poison_resist) && (py.flags.resist_poison)) {
  4291.     prt("You resist poison exceptionally well.", i++, j);
  4292.     pause_if_screen_full(&i, j);
  4293.     } else if ((py.flags.poison_resist) || (py.flags.resist_poison)) {
  4294.     prt("You are resistant to poison.", i++, j);
  4295.     pause_if_screen_full(&i, j);
  4296.     }
  4297.     if (py.flags.light_im) {
  4298.     prt("You are completely immune to lightning.", i++, j);
  4299.     pause_if_screen_full(&i, j);
  4300.     } else if ((py.flags.lght_resist) && (py.flags.resist_light)) {
  4301.     prt("You resist lightning exceptionally well.", i++, j);
  4302.     pause_if_screen_full(&i, j);
  4303.     } else if ((py.flags.lght_resist) || (py.flags.resist_light)) {
  4304.     prt("You are resistant to lightning.", i++, j);
  4305.     pause_if_screen_full(&i, j);
  4306.     }
  4307.     if (py.flags.light_resist) {
  4308.     prt("You are resistant to bright light.", i++, j);
  4309.     pause_if_screen_full(&i, j);
  4310.     }
  4311.     if (py.flags.dark_resist) {
  4312.     prt("You are resistant to darkness.", i++, j);
  4313.     pause_if_screen_full(&i, j);
  4314.     }
  4315.     if (py.flags.confusion_resist) {
  4316.     prt("You are resistant to confusion.", i++, j);
  4317.     pause_if_screen_full(&i, j);
  4318.     }
  4319.     if (py.flags.sound_resist) {
  4320.     prt("You are resistant to sonic attacks.", i++, j);
  4321.     pause_if_screen_full(&i, j);
  4322.     }
  4323.     if (py.flags.disenchant_resist) {
  4324.     prt("You are resistant to disenchantment.", i++, j);
  4325.     pause_if_screen_full(&i, j);
  4326.     }
  4327.     if (py.flags.chaos_resist) {
  4328.     prt("You are resistant to chaos.", i++, j);
  4329.     pause_if_screen_full(&i, j);
  4330.     }
  4331.     if (py.flags.shards_resist) {
  4332.     prt("You are resistant to blasts of shards.", i++, j);
  4333.     pause_if_screen_full(&i, j);
  4334.     }
  4335.     if (py.flags.nexus_resist) {
  4336.     prt("You are resistant to nexus attacks.", i++, j);
  4337.     pause_if_screen_full(&i, j);
  4338.     }
  4339.     if (py.flags.nether_resist) {
  4340.     prt("You are resistant to nether forces.", i++, j);
  4341.     pause_if_screen_full(&i, j);
  4342.     }
  4343.  
  4344. #if 0
  4345. /* Are these needed?  The player can see this...  For now, in here for
  4346.  * completeness... -CFT 
  4347.  */
  4348.     if (f & TR_STR) {
  4349.     prt("You are magically strong.", i++, j);
  4350.     pause_if_screen_full(&i, j);
  4351.     }
  4352.     if (f & TR_INT) {
  4353.     prt("You are magically intelligent.", i++, j);
  4354.     pause_if_screen_full(&i, j);
  4355.     }
  4356.     if (f & TR_WIS) {
  4357.     prt("You are magically wise.", i++, j);
  4358.     pause_if_screen_full(&i, j);
  4359.     }
  4360.     if (f & TR_DEX) {
  4361.     prt("You are magically agile.", i++, j);
  4362.     pause_if_screen_full(&i, j);
  4363.     }
  4364.     if (f & TR_CON) {
  4365.     prt("You are magically tough.", i++, j);
  4366.     pause_if_screen_full(&i, j);
  4367.     }
  4368.     if (f & TR_CHR) {
  4369.     prt("You are magically popular.", i++, j);
  4370.     pause_if_screen_full(&i, j);
  4371.     }
  4372.  
  4373. #endif
  4374.  
  4375.     if (py.flags.sustain_str) {
  4376.     prt("You will not become weaker.", i++, j);
  4377.     pause_if_screen_full(&i, j);
  4378.     }
  4379.     if (py.flags.sustain_int) {
  4380.     prt("You will not become dumber.", i++, j);
  4381.     pause_if_screen_full(&i, j);
  4382.     }
  4383.     if (py.flags.sustain_wis) {
  4384.     prt("You will not become less wise.", i++, j);
  4385.     pause_if_screen_full(&i, j);
  4386.     }
  4387.     if (py.flags.sustain_con) {
  4388.     prt("You will not become out of shape.", i++, j);
  4389.     pause_if_screen_full(&i, j);
  4390.     }
  4391.     if (py.flags.sustain_dex) {
  4392.     prt("You will not become clumsy.", i++, j);
  4393.     pause_if_screen_full(&i, j);
  4394.     }
  4395.     if (py.flags.sustain_chr) {
  4396.     prt("You will not become less popular.", i++, j);
  4397.     pause_if_screen_full(&i, j);
  4398.     }
  4399.     if (inventory[INVEN_LEFT].flags2 & TR_ATTACK_SPD ||
  4400.     inventory[INVEN_RIGHT].flags2 & TR_ATTACK_SPD) {
  4401.     prt("You can strike at your foes with uncommon speed.", i++, j);
  4402.     pause_if_screen_full(&i, j);
  4403.     }
  4404.  
  4405. /* this IS a bit redundant, but it prevents flags from other items from
  4406.  * affecting the weapon stats... -CFT
  4407.  */
  4408.     if (inventory[INVEN_WIELD].tval != TV_NOTHING) {
  4409.     f = inventory[INVEN_WIELD].flags;
  4410.     f2 = inventory[INVEN_WIELD].flags2;
  4411.     } else {
  4412.     f = 0L;
  4413.     f2 = 0L;
  4414.     }
  4415.     if (f & TR_CURSED) {
  4416.     if (inventory[INVEN_WIELD].name2 == SN_MORGUL)
  4417.         prt("Your weapon is truly foul.", i++, j);
  4418.     else if (inventory[INVEN_WIELD].name2 == SN_CALRIS)
  4419.         prt("Your bastard sword is wickedly accursed.", i++, j);
  4420.     else if (inventory[INVEN_WIELD].name2 == SN_MORMEGIL)
  4421.         prt("Your two-handed sword radiates an aura of unspeakable evil.", i++, j);
  4422.     else
  4423.         prt("Your weapon is accursed.", i++, j);
  4424.     pause_if_screen_full(&i, j);
  4425.     }
  4426.     if (f & TR_TUNNEL) {
  4427.     prt("Your weapon is an effective digging tool.", i++, j);
  4428.     pause_if_screen_full(&i, j);
  4429.     }
  4430.     if (f2 & TR_BLESS_BLADE) {
  4431.     prt("Your weapon has been blessed by the gods.", i++, j);
  4432.     pause_if_screen_full(&i, j);
  4433.     }
  4434.     if (f2 & TR_ATTACK_SPD) {
  4435.     prt("Your weapon strikes with uncommon speed.", i++, j);
  4436.     pause_if_screen_full(&i, j);
  4437.     }
  4438.     if (f2 & TR_SLAY_ORC) {
  4439.     prt("Your weapon is especially deadly against orcs.", i++, j);
  4440.     pause_if_screen_full(&i, j);
  4441.     }
  4442.     if (f2 & TR_SLAY_TROLL) {
  4443.     prt("Your weapon is especially deadly against trolls.", i++, j);
  4444.     pause_if_screen_full(&i, j);
  4445.     }
  4446.     if (f2 & TR_SLAY_GIANT) {
  4447.     prt("Your weapon is especially deadly against giants.", i++, j);
  4448.     pause_if_screen_full(&i, j);
  4449.     }
  4450.     if (f & TR_SLAY_ANIMAL) {
  4451.     prt("Your weapon is especially deadly against natural creatures.", i++, j);
  4452.     pause_if_screen_full(&i, j);
  4453.     }
  4454.     if (f & TR_SLAY_X_DRAGON) {
  4455.     prt("Your weapon is a great bane of dragons.", i++, j);
  4456.     pause_if_screen_full(&i, j);
  4457.     } else if (f & TR_SLAY_DRAGON) {
  4458.     prt("Your weapon is especially deadly against dragons.", i++, j);
  4459.     pause_if_screen_full(&i, j);
  4460.     }
  4461.     if (f2 & TR_SLAY_DEMON) {
  4462.     prt("Your weapon strikes at demons with holy wrath.", i++, j);
  4463.     pause_if_screen_full(&i, j);
  4464.     }
  4465.     if (f & TR_SLAY_UNDEAD) {
  4466.     prt("Your weapon strikes at undead with holy wrath.", i++, j);
  4467.     pause_if_screen_full(&i, j);
  4468.     }
  4469.     if (f & TR_SLAY_EVIL) {
  4470.     prt("Your weapon fights against evil with holy fury.", i++, j);
  4471.     pause_if_screen_full(&i, j);
  4472.     }
  4473.     if (f & TR_FROST_BRAND) {
  4474.     prt("Your frigid weapon freezes your foes.", i++, j);
  4475.     pause_if_screen_full(&i, j);
  4476.     }
  4477.     if (f & TR_FLAME_TONGUE) {
  4478.     prt("Your flaming weapon burns your foes.", i++, j);
  4479.     pause_if_screen_full(&i, j);
  4480.     }
  4481.     if (f2 & TR_LIGHTNING) {
  4482.     prt("Your weapon electrocutes your foes.", i++, j);
  4483.     pause_if_screen_full(&i, j);
  4484.     }
  4485.     if (f2 & TR_IMPACT)
  4486.     prt("The unbelievable impact of your weapon can cause earthquakes.", i++, j);
  4487.  
  4488.     pause_line(i);
  4489.     restore_screen();
  4490. }
  4491.  
  4492.  
  4493. #define NO_RES 0
  4494. #define SOME_RES 1
  4495. #define RESIST 2
  4496. #define IMMUNE 3
  4497. #define SUSCEPT 4
  4498. #define CHANGED 5
  4499. #define CONFUSED 6
  4500. #define MORE_CONF 7
  4501. #define DAZED 8
  4502. #define MORE_DAZED 16
  4503. #define DEAD 32
  4504.  
  4505. /* This function will process a bolt/ball/breath spell hitting a monster.
  4506.  * It checks for resistances, and reduces damage accordingly, and also
  4507.  * adds in what "special effects" apply to the monsters.  'rad' is used to
  4508.  * indicate the distance from "ground 0" for ball spells.  For bolts, rad
  4509.  * should be a 0 (this flags off some of the messages).  dam is changed
  4510.  * to reflect resistances and range. -CFT
  4511.  */
  4512.  
  4513. static void
  4514. spell_hit_monster(m_ptr, typ, dam, rad, y, x, by_player)
  4515. monster_type *m_ptr;
  4516. int           typ, *dam, rad, *y, *x;
  4517. int8u         by_player;
  4518. {
  4519.     register creature_type *r_ptr;
  4520.     int blind = (py.flags.status & PY_BLIND) ? 1 : 0;
  4521.     int res;            /* controls messages, using above #defines -CFT */
  4522.     vtype cdesc, outval;
  4523.  
  4524.     if (rad)
  4525.     *dam /= rad;        /* adjust damage for range... */
  4526.  
  4527.     *y = m_ptr->fy;        /* these only change if mon gets teleported */
  4528.     *x = m_ptr->fx; 
  4529.     r_ptr = &c_list[m_ptr->mptr];
  4530.     if (m_ptr->ml){
  4531.     if (r_ptr->cdefense & UNIQUE)
  4532.         sprintf(cdesc, "%s ", r_ptr->name);
  4533.     else
  4534.         sprintf(cdesc, "The %s ", r_ptr->name);
  4535.     }
  4536.     else
  4537.     strcpy(cdesc, "It ");
  4538.  
  4539.     res = NO_RES;        /* assume until we know different -CFT */
  4540.     switch ( typ ){        /* check for resists... */
  4541.       case GF_MAGIC_MISSILE:    /* pure damage, no resist possible */
  4542.     break;
  4543.       case GF_LIGHTNING:
  4544.     if (r_ptr->cdefense & IM_LIGHTNING) {
  4545.         res = RESIST;
  4546.         *dam /= 9;
  4547.         if (m_ptr->ml)
  4548.         c_recall[m_ptr->mptr].r_cdefense |= IM_LIGHTNING;
  4549.         }
  4550.     break;
  4551.       case GF_POISON_GAS:
  4552.     if (r_ptr->cdefense & IM_POISON) {
  4553.         res = RESIST;
  4554.         *dam /= 9;
  4555.         if (m_ptr->ml)
  4556.         c_recall[m_ptr->mptr].r_cdefense |= IM_POISON;
  4557.         }
  4558.     break;
  4559.       case GF_ACID:
  4560.     if (r_ptr->cdefense & IM_ACID) {
  4561.         res = RESIST;
  4562.         *dam /= 9;
  4563.         if (m_ptr->ml)
  4564.         c_recall[m_ptr->mptr].r_cdefense |= IM_ACID;
  4565.         }
  4566.     break;
  4567.       case GF_FROST:
  4568.     if (r_ptr->cdefense & IM_FROST) {
  4569.         res = RESIST;
  4570.         *dam /= 9;
  4571.         if (m_ptr->ml)
  4572.         c_recall[m_ptr->mptr].r_cdefense |= IM_FROST;
  4573.         }
  4574.     break;
  4575.       case GF_FIRE:
  4576.     if (r_ptr->cdefense & IM_FIRE) {
  4577.         res = RESIST;
  4578.         *dam /= 9;
  4579.         if (m_ptr->ml)
  4580.         c_recall[m_ptr->mptr].r_cdefense |= IM_FIRE;
  4581.         }
  4582.     break;
  4583.       case GF_HOLY_ORB:
  4584.     if (r_ptr->cdefense & EVIL) {
  4585.         *dam *= 2;
  4586.         res = SUSCEPT;
  4587.         if (m_ptr->ml)
  4588.         c_recall[m_ptr->mptr].r_cdefense |= EVIL;
  4589.         }
  4590.     break;
  4591.       case GF_ARROW:        /* for now, no defense... maybe it should have a
  4592.                    chance of missing? -CFT */
  4593.     break;
  4594.       case GF_PLASMA:        /* maybe IM_LIGHTNING (ball lightning is supposed
  4595.                    to be plasma) or IM_FIRE (since it's hot)? -CFT */
  4596.     if (!strncmp("Plasma", r_ptr->name, 6) ||
  4597.         (r_ptr->spells3 & BREATH_PL)){ /* if is a "plasma" monster,
  4598.                           or can breathe plasma, then
  4599.                           we assume it should be immune.
  4600.                           plasma bolts don't count, since
  4601.                           mage-types could have them, and
  4602.                           not deserve plasma-resist -CFT */
  4603.         res = RESIST;
  4604.         *dam *= 3;        /* these 2 lines give avg dam of .33, ranging */
  4605.         *dam /= (randint(6)+6); /* from .427 to .25 -CFT */
  4606.     }
  4607.     break;
  4608.       case GF_NETHER:        /* I assume nether is an evil, necromantic force,
  4609.                    so it doesn't hurt undead, and hurts evil less -CFT */
  4610.     if (r_ptr->cdefense & UNDEAD) {
  4611.         res = IMMUNE;
  4612.         *dam = 0;
  4613.         if (m_ptr->ml)
  4614.         c_recall[m_ptr->mptr].r_cdefense |= UNDEAD;
  4615.         }
  4616.     else if (r_ptr->spells2 & BREATH_LD) { /* if can breath nether, should get
  4617.                           good resist to damage -CFT */
  4618.         res = RESIST;
  4619.         *dam *= 3;  /* these 2 lines give avg dam of .33, ranging */
  4620.         *dam /= (randint(6)+6); /* from .427 to .25 -CFT */
  4621.     }
  4622.     else if (r_ptr->cdefense & EVIL) {
  4623.         *dam /= 2;    /* evil takes *2 for holy, so /2 for this... -CFT */
  4624.         res = SOME_RES;
  4625.         if (m_ptr->ml)
  4626.         c_recall[m_ptr->mptr].r_cdefense |= EVIL;
  4627.         }
  4628.     break;
  4629.       case GF_WATER:    /* water elementals should resist.  anyone else? -CFT */
  4630.     if ((r_ptr->cchar == 'E') && (r_ptr->name[0] == 'W')){
  4631.         res = IMMUNE;
  4632.         *dam = 0; /* water spirit, water ele, and Waldern -CFT */
  4633.         }
  4634.     break;
  4635.       case GF_CHAOS:
  4636.     if (r_ptr->spells2 & BREATH_CH){ /* assume anything that breathes
  4637.                         choas is chaotic enough to deserve resistance... -CFT */
  4638.         res = RESIST;
  4639.         *dam *= 3;  /* these 2 lines give avg dam of .33, ranging */
  4640.         *dam /= (randint(6)+6); /* from .427 to .25 -CFT */
  4641.         }
  4642.     if ((*dam <= m_ptr->hp) && /* don't bother if it's gonna die */
  4643.         !(r_ptr->spells2 & BREATH_CH) &&
  4644.         !(r_ptr->cdefense & UNIQUE) &&
  4645.         (randint(90) > r_ptr->level)) { /* then we'll polymorph it -CFT */
  4646.         res = CHANGED;
  4647.         if (poly(cave[*y][*x].cptr))
  4648.         *dam = 0; /* new monster was not hit by choas breath.  This also
  4649.                  makes things easier to handle */
  4650.     } /* end of choas-poly.  If was poly-ed don't bother confuse... it's
  4651.          too hectic to keep track of... -CFT */
  4652.     else if (!(r_ptr->cdefense & CHARM_SLEEP) &&
  4653.          !(r_ptr->spells2 & BREATH_CH) && /* choatics hard to confuse */
  4654.          !(r_ptr->spells2 & BREATH_CO)){   /* so are bronze dragons */
  4655.         if (m_ptr->confused > 0) { 
  4656.         res = MORE_CONF;
  4657.         if (m_ptr->confused < 240){ /* make sure not to overflow -CFT */
  4658.             m_ptr->confused += 7/(rad>0 ? rad : 1);
  4659.         }
  4660.         }
  4661.         else {
  4662.         res = CONFUSED;
  4663.         m_ptr->confused = (randint(11)+5)/(rad>0 ? rad : 1);
  4664.         }
  4665.     }
  4666.     break;
  4667.       case GF_SHARDS:
  4668.     if (r_ptr->spells2 & BREATH_SH){ /* shard breathers resist -CFT */
  4669.         res = RESIST;
  4670.         *dam *= 3;  /* these 2 lines give avg dam of .33, ranging */
  4671.         *dam /= (randint(6)+6); /* from .427 to .25 -CFT */
  4672.         }
  4673.     break;
  4674.       case GF_SOUND:
  4675.       if (r_ptr->spells2 & BREATH_SD){ /* ditto for sound -CFT */
  4676.       res = RESIST;
  4677.       *dam *= 2;
  4678.       *dam /= (randint(6)+6);
  4679.       }
  4680.     if ((*dam <= m_ptr->hp) && /* don't bother if it's dead */
  4681.         !(r_ptr->spells2 & BREATH_SD) &&
  4682.         !(r_ptr->spells3 & BREATH_WA)) { /* sound and impact breathers
  4683.                           should not stun -CFT */
  4684.         if (m_ptr->confused > 0) { 
  4685.         res = MORE_DAZED;
  4686.         if (m_ptr->confused < 220){ /* make sure not to overflow -CFT */
  4687.             m_ptr->confused += (randint(5)*2)/(rad>0 ? rad : 1);
  4688.         }
  4689.         }
  4690.         else {
  4691.         res = DAZED;
  4692.         m_ptr->confused = (randint(15)+10)/(rad>0 ? rad : 1);
  4693.         }
  4694.       }
  4695.     break;
  4696.       case GF_CONFUSION:
  4697.     if (r_ptr->spells2 & BREATH_CO){ 
  4698.         res = RESIST;
  4699.         *dam *= 2;
  4700.         *dam /= (randint(6)+6);
  4701.         }
  4702.     else if (r_ptr->cdefense & CHARM_SLEEP){
  4703.         res = SOME_RES;
  4704.         *dam /= 2; /* only some resist, but they also avoid confuse -CFT */
  4705.         }
  4706.     if ((*dam <= m_ptr->hp) && /* don't bother if it's dead */
  4707.         !(r_ptr->cdefense & CHARM_SLEEP) &&
  4708.         !(r_ptr->spells2 & BREATH_CH) && /* choatics hard to confuse */
  4709.         !(r_ptr->spells2 & BREATH_CO)) {  /* so are bronze dragons */
  4710.         if (m_ptr->confused > 0) { 
  4711.         res = MORE_CONF;
  4712.         if (m_ptr->confused < 240){ /* make sure not to overflow -CFT */
  4713.             m_ptr->confused += 7/(rad>0 ? rad : 1);
  4714.         }
  4715.         }
  4716.         else {
  4717.         res = CONFUSED;
  4718.         m_ptr->confused = (randint(11)+5)/(rad>0 ? rad : 1);
  4719.         }
  4720.     }
  4721.         break;
  4722.       case GF_DISENCHANT:
  4723.     if ((r_ptr->spells2 & BREATH_DI) ||
  4724.         !strncmp("Disen", r_ptr->name, 5)) {
  4725.         res = RESIST;
  4726.         *dam *= 3;  /* these 2 lines give avg dam of .33, ranging */
  4727.         *dam /= (randint(6)+6); /* from .427 to .25 -CFT */
  4728.         }
  4729.     break;
  4730.       case GF_NEXUS:
  4731.     if ((r_ptr->spells2 & BREATH_NE) ||
  4732.         !strncmp("Nexus", r_ptr->name, 5)) {
  4733.         res = RESIST;
  4734.         *dam *= 3;  /* these 2 lines give avg dam of .33, ranging */
  4735.         *dam /= (randint(6)+6); /* from .427 to .25 -CFT */
  4736.         }
  4737.     break;
  4738.       case GF_FORCE:
  4739.     if (r_ptr->spells3 & BREATH_WA){ /* breath ele force resists
  4740.                         ele force -CFT */
  4741.         res = RESIST;
  4742.         *dam *= 3;  /* these 2 lines give avg dam of .33, ranging */
  4743.         *dam /= (randint(6)+6); /* from .427 to .25 -CFT */
  4744.         }
  4745.     if ((*dam <= m_ptr->hp) &&
  4746.         !(r_ptr->spells2 & BREATH_SD) &&
  4747.         !(r_ptr->spells3 & BREATH_WA)){ /* sound and impact breathers
  4748.                            should not stun -CFT */
  4749.         if (m_ptr->confused > 0) { 
  4750.         res = MORE_DAZED;
  4751.         if (m_ptr->confused < 220){ /* make sure not to overflow -CFT */
  4752.             m_ptr->confused += (randint(5)+1)/(rad>0 ? rad : 1);
  4753.         }
  4754.         }
  4755.         else {
  4756.         res = DAZED;
  4757.         m_ptr->confused = randint(15)/(rad>0 ? rad : 1);
  4758.         }
  4759.     }
  4760.     break;
  4761.       case GF_INERTIA:
  4762.     if (r_ptr->spells3 & BREATH_SL){ /* if can breath inertia, then
  4763.                         resist it. */
  4764.         res = RESIST;
  4765.         *dam *= 3;  /* these 2 lines give avg dam of .33, ranging */
  4766.         *dam /= (randint(6)+6); /* from .427 to .25 -CFT */
  4767.         }
  4768.     break;
  4769.       case GF_LIGHT:
  4770.     if (r_ptr->spells3 & BREATH_LT){ /* breathe light to res light */
  4771.         res = RESIST;
  4772.         *dam *= 2;
  4773.         *dam /= (randint(6)+6);
  4774.         }
  4775.     else if (r_ptr->cdefense & HURT_LIGHT){
  4776.         res = SUSCEPT;
  4777.         *dam *= 2; /* hurt bad by light */
  4778.         }
  4779.     else if (r_ptr->spells3 & BREATH_DA){ /* breathe dark gets hurt */
  4780.         res = SUSCEPT;
  4781.         *dam = (*dam * 3)/2;
  4782.         }
  4783.     break;
  4784.       case GF_DARK:
  4785.     if (r_ptr->spells2 & BREATH_DA){ /* shard breathers resist -CFT */
  4786.         res = RESIST;
  4787.         *dam *= 2;
  4788.         *dam /= (randint(6)+6);
  4789.         }
  4790.     else if (r_ptr->cdefense & HURT_LIGHT){
  4791.         res = SOME_RES;
  4792.         *dam /= 2; /* hurt bad by light, so not hurt bad by dark */
  4793.         }
  4794.     else if (r_ptr->spells3 & BREATH_LT){ /* breathe light gets hurt */
  4795.         res = SUSCEPT;
  4796.         *dam = (*dam * 3)/2;
  4797.         }
  4798.     break;
  4799.       case GF_TIME:
  4800.     if (r_ptr->spells3 & BREATH_TI){ /* time breathers resist -CFT */
  4801.         res = RESIST;
  4802.         *dam *= 3;  /* these 2 lines give avg dam of .33, ranging */
  4803.         *dam /= (randint(6)+6); /* from .427 to .25 -CFT */
  4804.         }
  4805.     break;
  4806.       case GF_GRAVITY:
  4807.     if (r_ptr->spells3 & BREATH_GR){ /* breathers resist -CFT */
  4808.         res = RESIST;
  4809.         *dam *= 3;  /* these 2 lines give avg dam of .33, ranging */
  4810.         *dam /= (randint(6)+6); /* from .427 to .25 -CFT */
  4811.         }
  4812.     else {
  4813.         if (*dam <= m_ptr->hp) {
  4814.         teleport_away(cave[m_ptr->fy][m_ptr->fx].cptr, 5);
  4815.         *y = m_ptr->fy; /* teleported, so let outside world know monster moved! */
  4816.         *x = m_ptr->fx; 
  4817.         }
  4818.         }
  4819.     break;
  4820.       case GF_MANA: /* raw blast of power. no way to resist, is there? */
  4821.     break;
  4822.       case GF_METEOR: /* GF_METEOR is basically a powerful magic-missile
  4823.              ball spell.  I only made it a different type
  4824.              so I could make it a different color -CFT */
  4825.     break;
  4826.       case GF_ICE: /* ice is basically frost + cuts + stun -CFT */
  4827.     if (r_ptr->cdefense & IM_FROST) {
  4828.         res = RESIST;
  4829.         *dam /= 9;
  4830.         if (m_ptr->ml)
  4831.         c_recall[m_ptr->mptr].r_cdefense |= IM_FROST;
  4832.         }
  4833.     if ((*dam <= m_ptr->hp) &&
  4834.         !(r_ptr->spells2 & BREATH_SD) &&
  4835.         !(r_ptr->spells3 & BREATH_WA)){  /* sound and impact breathers
  4836.                           should not stun -CFT */
  4837.         if (m_ptr->confused > 0) { 
  4838.         res += MORE_DAZED;
  4839.         if (m_ptr->confused < 220){ /* make sure not to overflow -CFT */
  4840.             m_ptr->confused += (randint(5)+1)/(rad>0 ? rad : 1);
  4841.         }
  4842.         }
  4843.         else {
  4844.         res += DAZED;
  4845.         m_ptr->confused = randint(15)/(rad>0 ? rad : 1);
  4846.         }
  4847.     }
  4848.     break;
  4849.       default:
  4850.     msg_print("Unknown typ in spell_hit_monster.  This may mean trouble.");
  4851.     } /* end switch for saving throws and extra effects */
  4852.     
  4853.     if (res == CHANGED)
  4854.     sprintf(outval, "%schanges!",cdesc);
  4855.     else if ((*dam > m_ptr->hp) &&
  4856.          (by_player || !(c_list[m_ptr->mptr].cdefense & UNIQUE))) {
  4857.     res = DEAD;
  4858.     if ((c_list[m_ptr->mptr].cdefense & (DEMON|UNDEAD|MINDLESS)) ||
  4859.         (c_list[m_ptr->mptr].cchar == 'E') ||
  4860.         (c_list[m_ptr->mptr].cchar == 'v') ||
  4861.         (c_list[m_ptr->mptr].cchar == 'g') ||
  4862.         (c_list[m_ptr->mptr].cchar == 'X'))
  4863.         sprintf(outval, "%sis destroyed.", cdesc);
  4864.     else
  4865.         sprintf(outval, "%sdies.", cdesc);
  4866.     }
  4867.     else switch (res) {
  4868.       case NO_RES:
  4869.     sprintf(outval, "%sis hit.",cdesc);
  4870.     break;
  4871.       case SOME_RES:
  4872.     sprintf(outval, "%sresists somewhat.",cdesc);
  4873.     break;
  4874.       case RESIST:
  4875.     sprintf(outval, "%sresists.",cdesc);
  4876.     break;
  4877.       case IMMUNE:
  4878.     sprintf(outval, "%sis immune.",cdesc);
  4879.     break;
  4880.       case SUSCEPT:
  4881.     sprintf(outval, "%sis hit hard.",cdesc);
  4882.     break;
  4883.       case CONFUSED:
  4884.     sprintf(outval, "%sis confused.",cdesc);
  4885.     break;
  4886.       case MORE_CONF:
  4887.     sprintf(outval, "%sis more confused.",cdesc);
  4888.     break;
  4889.       case DAZED:
  4890.     sprintf(outval, "%sis dazed.",cdesc);
  4891.     break;
  4892.       case MORE_DAZED:
  4893.     sprintf(outval, "%sis more dazed.",cdesc);
  4894.     break;
  4895.       case (DAZED+RESIST):
  4896.       sprintf(outval, "%sresists, but is dazed anyway.",cdesc);
  4897.     break;
  4898.       case (MORE_DAZED+RESIST):
  4899.       sprintf(outval, "%sresists, but still is more dazed.",cdesc);
  4900.     break;
  4901.       default:
  4902.     sprintf(outval,"%sis affected in a mysterious way.",cdesc);
  4903.     }
  4904.     if (rad || (res != NO_RES)) { /* don't show normal hit msgs for bolts -CFT */
  4905.     if (!blind)
  4906.         msg_print(outval);
  4907.     }    
  4908. }
  4909.  
  4910. /* This fn provides the ability to have a spell blast a line of creatures
  4911.    for damage.  It should look pretty neat, too... -CFT */
  4912. void
  4913. line_spell(typ, dir, y, x, dam)
  4914. int typ, dir, y, x, dam;
  4915. {
  4916.     int ny,nx, dis = 0, flag = FALSE;
  4917.     int t, tdam;
  4918.     monster_type *m_ptr;
  4919.     cave_type *c_ptr;
  4920.     int8u path[OBJ_BOLT_RANGE+5][3]; /* pre calculate "flight" path, makes bolt
  4921.                     calc faster because fns more likely to be in mem.
  4922.                     Also allows redraw at reasonable spd -CFT */  
  4923.  
  4924.     path[0][0] = y;  path[0][1] = x; /* orig point */
  4925.     do {
  4926.     (void)mmove(dir, &y, &x);
  4927.     dis++;
  4928.     path[dis][0] = y;  path[dis][1] = x;
  4929.     if ((dis>OBJ_BOLT_RANGE) || (cave[y][x].fval >= MIN_CLOSED_SPACE))
  4930.         flag = TRUE;
  4931.     } while (!flag);
  4932.  
  4933.     flag = FALSE;
  4934.     dis = 0;
  4935.     do {
  4936.     dis++;
  4937.     y = path[dis][0];  x = path[dis][1];
  4938.     c_ptr = &cave[y][x];
  4939.     if ((dis > OBJ_BOLT_RANGE) || c_ptr->fval >= MIN_CLOSED_SPACE)
  4940.         flag = TRUE;    /* then stop */
  4941.     else {
  4942.         if (c_ptr->cptr > 1) { /* hit a monster! */
  4943.         tdam = dam;
  4944.         m_ptr = &m_list[c_ptr->cptr];
  4945.  
  4946.         if (!(py.flags.status & PY_BLIND) && panel_contains(y,x)){
  4947.             /* temp light monster to show it... */
  4948.             t = c_ptr->pl;
  4949.             c_ptr->pl = TRUE;
  4950.             update_mon((int)c_ptr->cptr);
  4951.             c_ptr->pl = t;
  4952.             put_qio();    /* draw monster */
  4953.         }
  4954.  
  4955.         /* check resists */
  4956.         spell_hit_monster(m_ptr, typ, &tdam, 1, &ny, &nx, TRUE);
  4957.         c_ptr = &cave[ny][nx]; /* may be new loc if tele by grav warp */
  4958.  
  4959.         (void) mon_take_hit((int)c_ptr->cptr, tdam, TRUE); /* hurt it */
  4960.         }
  4961.         if (!(py.flags.status & PY_BLIND)) {
  4962.         for(t=1;t<=dis;t++)
  4963.             if (panel_contains(path[t][0],path[t][1])){
  4964. #ifdef TC_COLOR
  4965.             if (!no_color_flag) textcolor(bolt_color(typ));
  4966. #endif
  4967.             print(bolt_char(path[t][0],path[t][1],path[t-1][0], path[t-1][1]),
  4968.                   path[t][0], path[t][1]);
  4969. #ifdef TC_COLOR
  4970.             if (!no_color_flag) textcolor(LIGHTGRAY);
  4971. #endif
  4972.             }
  4973.         put_qio();    /* show line */
  4974. #ifdef MSDOS
  4975.         delay(8 * delay_spd);
  4976. #else
  4977.         usleep(8000 * delay_spd);
  4978. #endif      
  4979.         } /* if !blind */
  4980.     } /* if hit monster */
  4981.     } while (!flag);        /* end of effects loop */
  4982.   
  4983.     if (!(py.flags.status & PY_BLIND)) { /* now erase it -CFT */
  4984.     for(t=1;t<=dis;t++){    /* erase piece-by-piece... */
  4985.         lite_spot(path[t][0], path[t][1]);
  4986.         for(tdam=t+1;tdam<dis;tdam++){
  4987.         if (panel_contains(path[tdam][0], path[tdam][1])){
  4988. #ifdef TC_COLOR
  4989.             if (!no_color_flag) textcolor(bolt_color(typ));
  4990. #endif
  4991.             print(bolt_char(path[tdam][0],path[tdam][1],path[tdam-1][0],
  4992.                     path[tdam-1][1]), path[tdam][0], path[tdam][1]);
  4993. #ifdef TC_COLOR
  4994.             if (!no_color_flag) textcolor(LIGHTGRAY);
  4995. #endif
  4996.         }
  4997.         }
  4998.         put_qio();
  4999. #ifdef MSDOS
  5000.         delay(8 * delay_spd);
  5001. #else
  5002.         usleep(8000 * delay_spd);
  5003. #endif      
  5004.     } /* for each piece */
  5005.     } /* if !blind */
  5006. }  
  5007.